【发布时间】:2010-12-26 02:35:43
【问题描述】:
我只是在使用 NFA 进行字符串识别。我有一个宏,它创建一个函数,该函数消耗输入并将其余部分传递给其他一些函数。因为我的 NFA 图中可能存在循环,所以我使用 letrec 将整个事情放在一起。下面是一些代码(在 PLT-Scheme 中测试过):
(define-syntax-rule (match chars next accepting)
; a function that consumes a list of chars from a list l.
; on success (if there's more to do) invokes each of next on the remainder of l.
(lambda (l)
(let loop ((c chars) (s l))
(cond
((empty? c)
(cond
((and (empty? s) accepting) #t)
(else
(ormap (lambda (x) (x s)) next))))
((empty? s) #f)
((eq? (car c) (car s))
(loop (cdr c) (cdr s)))
(else #f)))))
; matches (a|b)*ac. e .g. '(a a b b a c)
(define (matches? l)
(letrec
([s4 (match '( ) '() #t)]
[s3 (match '(c) `(,s4) #f)]
[s2 (match '(a) `(,s3) #f)]
[s1 (match '( ) `(,s2 ,s5) #f)]
[s5 (match '( ) `(,s6 ,s7) #f)]
[s6 (match '(a) `(,s8) #f)]
[s7 (match '(b) `(,s8) #f)]
[s8 (match '( ) `(,s1) #f)])
(s1 l)))
(matches? '(a c))
(matches? '(a b b b a c))
(matches? '(z a b b b a c))
现在,如果我有一个简单的数据结构来表示我的 NFA,比如列表列表。例如
'((s4 () () #t)
(s3 (c) (s4) #f)
...)
我的问题是:如何将该列表转换为之前的 letrec 语句?我对宏不太了解,我的理解是我可能不应该使用 eval。
【问题讨论】:
-
出于好奇,
match是否有任何理由成为宏而不是常规函数? -
调用函数会导致参数被评估,需要避免这些参数才能让 letrec 工作。