ISL +中的有限状态机仿真实现(球拍)

时间:2018-10-30 18:43:18

标签: racket state-machine racket-student-languages

我是一个新手,我自己通过HTDP2(Felleisen等人)工作,但陷入了第四章“交错数据”的问题380。问题是在创建DSL的背景下进行的,但是我首先重新认识了通用的FSM Simulator,并提供了以下代码:

; 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"))))

然后问题描述如下:

重新格式化1Transition的数据定义,以便可以将转换限制为某些击键。尝试制定更改,以使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”,它将进入“绿色” FSM状态,但是它将不接受“ g”进入以下状态等等。

如果我从(simulate "yellow" fsm-traffic)开始世界程序,那么将呈现FSM状态“黄色”,但不会过渡到任何其他状态(error子句已激活);类似地,以“绿色”作为起始状态。

我的直觉是,由于我首先将fsm-traffic定义为“红色”状态,因此它接受其输入以转换为“绿色”,但是由于其他状态big-bang并未发生这种情况将transitions参数正确“杂耍”。但我只是不知道该如何解决。从数据定义开始,我也不知道是否出错。

预先感谢您对我的帮助。

P.D。请让我知道我是否遵守关于stackoverflow的发布规则(这是我的第一篇文章:)。

1 个答案:

答案 0 :(得分:0)

您确定问题的根源是正确的。您首先以fsm-traffic状态定义了"red",并定义了"r"转换,然后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都存在任何转换时,应该为真。

这个带有“ any ”和“ both ”的目的陈述听起来很复杂,以至于它应该成为自己的功能。使用我们刚刚完成的输入,输出和目的:

;; 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)))))

但是实际主体应该同时取决于statekey

就像这同时取决于两者一样,find函数也应该同时取决于statekey

;; 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。

这足以让您继续。