代码之家  ›  专栏  ›  技术社区  ›  old_dd

Racket博士,帮助从列表中获取元素

  •  1
  • old_dd  · 技术社区  · 8 年前

    我正在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)]
        )
      )
    

    因此,目前,如果运行此脚本和类型:(transition current\u state in\u string delta\u 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))是(writeln current\u state)命令在lambda函数运行以在delta\u fn列表中查找其匹配项后的结果。我想我可以直接在那里键入(cdr(cdr current_state))来获取该输出中的第三项,但是((0“a”0))不是一个列表,我不能像列表一样对其进行操作。

    所以我的问题是:((0“a”0))是什么?为什么当前_状态设置为该状态而不是(0“a”0)?

    任何帮助都将不胜感激,请知道我对函数式编程非常陌生,所以请使用small words=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)]
        )
      )
    
    1 回复  |  直到 8 年前
        1
  •  1
  •   Will Ness Derri Leahy    8 年前

    您正在重用变量 current_state . 不要那样做!

    首先是0,初始状态。

    然后你把它改成一个完全不同的值,结果是 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)
    

    你可以用 当前_状态 代替 next_state ,但那只是一团糟。最好让所有变量都有意义,并具有与其含义相对应的适当值。否则,很容易在所有复杂的混乱中迅速迷失方向。

    此外,使用 set! 通常是不赞成的。在Scheme中,我们通常声明一个新的变量以供以后使用,如

        (let ((next_state (car (cdr ..... ))))
            ; recursive call .....