我是一个在HTDP2工作的新手(Felleisen等人)但我自己却被困在第四章-Intertwined数据的第380号问题上。问题在创建DSL的范围内,但我首先重新认识了一个通用的FSM模拟器,并提供了以下代码:
; An FSM is a [List-of 1Transition]
; A 1Transition is a list of two items:
; (cons FSM-State (cons FSM-State '()))
; An FSM-State is a String that specifies a color
; data examples
(define fsm-traffic
'(("red" "green") ("green" "yellow") ("yellow" "red")))
; FSM FSM-State -> FSM-State
; matches the keys pressed by a player with the given FSM
(define (simulate state0 transitions)
(big-bang state0 ; FSM-State
[to-draw
(lambda (current)
(overlay (text current 12 "black")
(square 100 "solid" current)))]
[on-key
(lambda (current key-event)
(find transitions current))]))
; [X Y] [List-of [List X Y]] X -> Y
; finds the matching Y for the given X in alist
(define (find alist x)
(local ((define fm (assoc x alist)))
(if (cons? fm) (second fm) (error "not found"))))然后将问题说明如下:
重新制定1转换的数据定义,这样就可以将转换限制在特定的击键上。尝试制定更改,以便find继续工作而不进行更改。您还需要更改哪些内容才能使整个程序正常工作?设计配方的哪一部分提供了答案?原始练习声明见练习229。
练习229引入了一个结构类型定义来跟踪状态和转换,但是由于问题声明要求我保持在提供的find函数内,所以很难想出一个类似的结构类型的定义。相反,我提出了以下数据定义:
; An FSM is a [List-of Transition]
; A Transition is a two-item list of the following form:
; (cons FSM-State (cons (cons KeyEvent (cons FSM-State '()))'()))
; data example
(define fsm-traffic (list (list "red" (list "r" "green"))
(list "green" (list "g" "yellow"))
(list "yellow" (list "y" "red"))))因此,调用(find fsm-traffic "green"),我得到(list "g" "yellow"),因此我修改了on-key子句,如下所示:
(lambda (current key-event)
(if (string=? key-event (first (first (rest (first transitions)))))
(second (find transitions current))
(error "invalid input")))现在,如果我用(simulate "red" fsm-traffic) State0启动程序,如果我按下"r“,它会转到"green”FSM-State,但是它不会接受"g“转到下面的状态,等等。
如果我用(simulate "yellow" fsm-traffic)开始这个world程序,那么FSM-State“黄色”就会呈现出来,但是它不会转换到任何其他状态( error子句被激活);同样地,以"green“作为起始状态。
我的预感是,由于我首先用"red“状态定义了fsm-traffic,所以它接受它的输入以过渡到”绿色“,但是由于其他状态没有发生相同的情况,所以big-bang没有向右”篡改“transitions参数。但我不知道怎么解决这个问题。从数据定义开始,我也不知道自己是否出了问题。
提前谢谢你帮我忙。
请告诉我是否遵守了在堆栈溢出上发布的规则(这是我的第一篇文章:)。
发布于 2018-10-30 20:06:31
您正确地确定了问题的根源。首先使用fsm-traffic状态和"r"转换定义了on-key,on-key处理程序只查看first。它在if问题中这样做:
(string=? key-event (first (first (rest (first transitions)))))
; ^ ^
; | this makes it only look at `"red"`
; this makes it only look at `"r"` within that这个if问题似乎很复杂。就像如果它是一个具有签名和目的的函数一样,我们可以设计这个表达式的输入、输出和用途。
投入:它应该依赖什么?
哪些键有效取决于转换表,但也取决于当前状态。这就是为什么只有"r"在"red"状态上有效,而"g"在"green"状态上有效的原因。因此,其投入如下:
current : FSM-State
key-event : KeyEvent
transitions : FSM现有表达式忽略current。
产出和目的
这是一个if问题,所以它应该输出一个Boolean。此布尔值的目的是确定密钥在当前状态下是否有效。
当表中存在current状态和key-event的任何转换时,应该是正确的。
这个带有“任意”和“两者”的目的声明听起来很复杂,应该是它自己的功能。使用我们刚才所做的输入、输出和目的:
;; FSM-State KeyEvent FSM -> Boolean
;; Determines whether there is any transition in the FSM table for both the current
;; state and the key event.
(define (transition-for-state-and-key? state key table)
....)你身体的当前表达式--不包括state,
(string=? key (first (first (rest (first table)))))但是实际的身体应该同时依赖于state和key。
与此类似,find函数也应该同时依赖于state和key。
;; FSM-State KeyEvent FSM -> FSM-State
;; Finds the matching transition-state from the given state with the given key in the table.
(define (find-transition-state state key table)
....)注意transition-for-state-and-key?和find-transition-state之间的关系。transition-for-state-and-key?函数应该在find-transition-state不会出错时准确地返回true。
这应该足以让你继续下去。
https://stackoverflow.com/questions/53070925
复制相似问题