以编程方式填写Scheme中的letrec。宏还是评估?
我只是用 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。
I'm just playing with an NFA for string recognition. I have a macro that creates a function which consumes input and passes on the rest to some other functions. Because there might be loops in my NFA graph, I'm using letrec to put the whole thing together. Here is some code (been testing in 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))
Now, what if I had a simple data-structure to represent my NFA, like a list of lists. e.g.
'((s4 () () #t)
(s3 (c) (s4) #f)
...)
My question is: How would I turn that list into the former letrec statement? I'm not too good with Macros and my understanding is that I probably shouldn't be using eval.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果该列表在编译时已知(我的意思是,在程序开始运行之前),那么您可以使用宏。否则您必须使用
eval
。没关系。这是 eval 的良好用途之一。 :)
If the list is known at compile time (what I mean is, before your program starts running) then you can use a macro. Otherwise you must use
eval
.It's ok. This is one of the good uses for eval. :)
我想出了这个宏,它似乎可以完成这项工作
(我也不是专家):
技巧是使用中间形式来创建“替换循环”,
并保留标识符(参见
let-bindings
)来区分这些中间形式来自直接使用宏。
I came up with this macro which seems to do the job
(I'm not an expert either):
The trick is to use intermediate forms to create "subtitution loops",
and reserve identifiers (cf.
let-bindings
) to distinguish these intermediate formsfrom direct usage of the macro.
我认为你的问题可以分为2个子问题:
第二个子问题很简单:
第一个问题,我有一个 DFA 示例,你可以自己写一个NFA:
好吧,也许define-macro是实现apply-macro的更好方法。
I think your problem can be seprate into 2 subproblem:
the second subproblem is easy:
the first question,I have a DFA sample,you can write a NFA by youself:
well,may be define-macro is a better way to implement apply-macro.