Macros 以编程方式填写letrec in方案。宏还是评估?
我只是在玩NFA来识别字符串。我有一个宏,它创建一个函数,该函数使用输入并将其余的传递给其他函数。因为我的NFA图中可能有循环,所以我使用letrec将整个过程放在一起。以下是一些代码(已在PLT方案中测试): 现在,如果我有一个简单的数据结构来表示我的NFA,比如列表列表。e、 gMacros 以编程方式填写letrec in方案。宏还是评估?,macros,scheme,Macros,Scheme,我只是在玩NFA来识别字符串。我有一个宏,它创建一个函数,该函数使用输入并将其余的传递给其他函数。因为我的NFA图中可能有循环,所以我使用letrec将整个过程放在一起。以下是一些代码(已在PLT方案中测试): 现在,如果我有一个简单的数据结构来表示我的NFA,比如列表列表。e、 g '((s4 () () #t) (s3 (c) (s4) #f) ...) 我的问题是:我如何将该列表转化为前letrec声明?我不太擅长宏,我的理解是我可能不应该使用eval 如果列表在编译时已知(我
'((s4 () () #t)
(s3 (c) (s4) #f)
...)
我的问题是:我如何将该列表转化为前letrec声明?我不太擅长宏,我的理解是我可能不应该使用eval 如果列表在编译时已知(我的意思是,在程序开始运行之前),则可以使用宏。否则必须使用
eval
没关系。这是评估的良好用途之一。:) 我想出了这个宏,它似乎可以完成这项工作 (我也不是专家): 诀窍是使用中间形式创建“子替换循环”, 和保留标识符(参见
let bindings
)来区分这些中间形式
直接使用宏。我认为您的问题可以分为两个子问题:
(define-syntax apply-macro
(syntax-rules ()
((_ macro ls)
(eval
`(macro ,@ls)
(interaction-environment)))))
;(define ls '(1 2 3))
;(apply-macro if ls)=>2
第一个问题,我有一个DFA样本,你可以自己写一个NFA:
(define-syntax make-DFA
(syntax-rules (: ->)
((_ init-state (state : result (symbol -> next) ...) ...)
(letrec
((state
(lambda(sigma)
(cond
((null? sigma) result)
(else
(case (car sigma)
((symbol)
(next (cdr sigma)))...
(else false))))))... )
init-state))))
(define DFA1
(make-DFA q1
(q1 : true (#\a -> q2)
(#\b -> q3))
(q2 : false (#\a -> q1)
(#\b -> q4))
(q3 : false (#\a -> q4)
(#\b -> q1))
(q4 : true (#\a -> q3)
(#\b -> q2))))
(DFA1 (string->list "ababa"));=>#f
嗯,也许define macro是实现apply macro的更好方法。出于好奇,有没有理由将
match
作为一个宏而不是一个常规函数?调用函数会导致对参数进行求值,这需要避免让letrec工作。+1。我感谢你的辛勤工作和榜样,但我的问题是我的列表是按程序生成的。比如说,为了便于示例,它存储为nfa规则
,开始是s1
。然后我希望能够执行(nfa s1 nfa规则)
。让宏“窥视”nfa规则并迭代内容是我遇到的问题。我认为Jason所说的可能是正确的。如果我在编译时知道这个列表,我可以使用你的宏来简化编码。但是,如果列表是以编程方式生成的,我可能必须在运行时使用eval
将其转换为适当的代码。如果您要将NFA作为数据进行操作,那么将其作为数据来实现可能会更简单,并且当您必须在代码中硬编码某些NFA时,使用宏只是为了便于输入。你的letrec/macro技巧很巧妙,但是:-)而且,没有一个宏会“窥探”任何变量:在进行任何计算之前,它们会操作代码,所以就它们而言,nfa规则
只是一个词。听你这么说重申了我认为是正确的。除非有人证明不是这样,否则你会被选中。
(define-syntax apply-macro
(syntax-rules ()
((_ macro ls)
(eval
`(macro ,@ls)
(interaction-environment)))))
;(define ls '(1 2 3))
;(apply-macro if ls)=>2
(define-syntax make-DFA
(syntax-rules (: ->)
((_ init-state (state : result (symbol -> next) ...) ...)
(letrec
((state
(lambda(sigma)
(cond
((null? sigma) result)
(else
(case (car sigma)
((symbol)
(next (cdr sigma)))...
(else false))))))... )
init-state))))
(define DFA1
(make-DFA q1
(q1 : true (#\a -> q2)
(#\b -> q3))
(q2 : false (#\a -> q1)
(#\b -> q4))
(q3 : false (#\a -> q4)
(#\b -> q1))
(q4 : true (#\a -> q3)
(#\b -> q2))))
(DFA1 (string->list "ababa"));=>#f