I'm a newbie working through HTDP2 (Felleisen et al.) on my own but have gotten stuck on question #380 of chapter IV -Intertwined Data. The problem is within the context of creating a DSL but I am first reacquainted with a general FSM Simulator and provided with the following code:
; 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"))))
The problem is then stated as follows:
Reformulate the data definition for 1Transition so that it is possible to restrict transitions to certain keystrokes. Try to formulate the change so that find
continues to work without change. What else do you need to change to get the complete program to work? Which part of the design recipe provides the answer(s)? See exercise 229 for the original exercise statement.
Exercise 229 introduces a structure type definition to keep track of the states and the transitions but since the problem statement asks me to stay within the provided find
function I am hard pressed to come up with a similar structure type of definition. Instead I came up with the following Data Definition:
; 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"))))
Hence calling (find fsm-traffic "green")
I get (list "g" "yellow")
I have thus modified the on-key
clause as follows:
(lambda (current key-event)
(if (string=? key-event (first (first (rest (first transitions)))))
(second (find transitions current))
(error "invalid input")))
Now if I start the program with (simulate "red" fsm-traffic)
State0 is rendered and if I press "r" it goes to "green" FSM-State but then it won't accept "g" to go to the following state and so on.
If I begin the world-program with (simulate "yellow" fsm-traffic)
then FSM-State "yellow" is rendered but it will not transition to any other state (the error
clause is activated); similarly with "green" as the starting state.
My hunch is that since I defined fsm-traffic
with the "red" state first it accepts its input to transition to "green" but since the same is not happening with the other states big-bang
is not "juggling" the transitions
parameter right. But I just don't know how to fix that. I also don't know if I've gone wrong since the start with my data definition.
Thank you in advance for helping me out.
P.D. please let me know if I have followed the rules on posting on stackoverflow (this is my first post :).