【发布时间】:2015-02-28 16:45:42
【问题描述】:
如果 Racket 的 match 宏是一个函数,我可以这样做:
(define my-clauses (list '[(list '+ x y) (list '+ y x)]
'[_ 42]))
(on-user-input
(λ (user-input)
(define expr (get-form-from-user-input user-input)) ; expr could be '(+ 1 2), for example.
(apply match expr my-clauses)))
我认为有两种截然不同的方法可以做到这一点。一种是将my-clauses 移动到宏世界中,并制作一个类似这样的宏(不起作用):
(define my-clauses (list '[(list '+ x y) (list '+ y x)]
'[_ 42]))
(define-syntax-rule (match-clauses expr)
(match expr my-clauses)) ; this is not the way it's done.
; "Macros that work together" discusses this ideas, right? I'll be reading that today.
(on-user-input
(λ (user-input)
(define expr (get-form-from-user-input user-input)) ; expr could be '(+ 1 2), for example.
(match-clauses expr)))
替代方案,最终可能会更好,因为它允许我在运行时更改my-clauses,它将以某种方式在运行时执行模式匹配。有什么方法可以在运行时值上使用匹配?
In this questionRyan Culpepper 说
如果不使用
eval,则无法创建形式参数和主体作为运行时值(S 表达式)给出的函数。
所以我想我必须使用 eval,但天真的方法行不通,因为 match 是一个宏
(eval `(match ,expr ,@my-clauses) (current-namespace))
我通过指南中的以下巫术得到了想要的结果
(define my-clauses '([(list'+ x y) (list '+ y x)]
[_ 42]))
(define-namespace-anchor a)
(define ns (namespace-anchor->namespace a))
(eval `(match '(+ 1 2) ,@my-clauses) ns) ; '(+ 2 1)
模式匹配现在是否在运行时发生?这是个坏主意吗?
【问题讨论】:
-
起初您描述希望
match成为一个函数——但关于在运行时更改子句的部分似乎并不是您最初的、您想要它的根本原因。您能否详细说明您希望match成为函数的原始/主要原因? (也许如果我们了解您想要做什么,我们可以提出更多想法?)
标签: macros pattern-matching racket