我正在研究Racket博士的有限状态机,需要一些帮助来提取转换函数中的下一个状态。
现在,我没有检查以确保字符串中的字符与字母表匹配,或者最终状态是否在最终状态列表中,或者任何其他状态,直到我可以递归地从状态转换到状态
这就是我现在所处的位置:
#lang racket
(require math/array)
(define in_string (list "a" "b" "b" "b"))
(define alphabet (list "a" "b"))
(define initial_state 0)
(define final_states (list 2))
(define delta_fn (list
(list 0 "a" 0)
(list 0 "b" 1)
(list 1 "a" 0)
(list 1 "b" 1)))
(define current_state initial_state)
(define (transition current_state in_string delta_fn)
(writeln current_state)
(writeln in_string)
(writeln delta_fn)
(cond
[(empty? in_string) (writeln current_state)]
[else
(let ([input (car in_string)])
(set! current_state (filter (lambda (v)
(match v
[(list (== current_state) (== input) _) #t]
[_ #f]))
delta_fn)))
(writeln current_state)]
;(transition current_state in_string delta_fn)]
)
)
所以目前,如果您运行此脚本并且类型为:(转换current_state in_string delta_fn),您将获得以下输出:
> (transition current_state in_string delta_fn)
0
("a" "b" "b" "b")
((0 "a" 0) (0 "b" 1) (1 "a" 0) (1 "b" 1))
((0 "a" 0))
最后一行:((0" a" 0))是lambda函数运行以在delta_fn列表中找到匹配项后(writeln current_state)命令的结果。我想我可以直接输入(cdr(cdr current_state))来获得该输出中的第三项,但是((0" a" 0))不是列表而我不能像列表一样对它进行操作。
所以我的问题是:什么是((0" a" 0))?为什么current_state设置为而不是'(0" a" 0)?
任何帮助都会非常感激,请知道我对函数式编程很新,所以使用小字= P
的解决方案!
(define (transition current_state in_string delta_fn)
(cond
[(empty? in_string) (writeln current_state)]
[else
(let ([input (car in_string)])
(set! filtered_delta_fn (filter (lambda (v)
(match v
[(list (== current_state) (== input) _) #t]
[_ #f]))
delta_fn)))
(set! next_state (car (cdr (cdr (car filtered_delta_fn)))))
(transition next_state (cdr in_string) delta_fn)]
)
)
答案 0 :(得分:1)
您正在重复使用变量current_state
。不要那样做!
首先它是0,初始状态。
然后你改变它以保持一个完全不同的值,即filter
操作的结果。相反,请使用一些临时变量,因此current_state
尚未更改。
现在,filter
会返回您询问的值((0 "a" 0))
,因为delta_fn
中的所有条目都保留了与您的条件相匹配的条目,列表(0 "a" 0)
。因此,筛选后的列表中包含一个匹配的条目。
要从中找到您的下一个状态,只需致电
即可(set! next_state (car (cdr (cdr (car filtered_delta_fn)))))
; (0 "a" 0)
; ("a" 0)
; (0)
; 0
其中filtered_delta_fn
将是上面提到的临时变量。
然后,递归调用现在将是
(transition next_state in_string delta_fn)
您可以使用current_state
代替next_state
,但这只是凌乱。让所有变量有意义,使用与其含义相对应的适当值更好。否则,很容易在所有复杂的混乱中迅速迷失。
此外,set!
的使用通常不受欢迎。在Scheme中,我们通常声明一个以后要使用的新变量,比如
(let ((next_state (car (cdr ..... ))))
; recursive call .....