我正在尝试编写一个为core.match宏生成模式的宏。
(defmacro match2
[state i predecessor]
`(match ~[state]
[(~(vec (concat (repeat i '_)
predecessor
'(& r)))
:seq)] ~i
:else false))
如果我直接使用硬编码的前辈,这可以正常工作:
(match2 ["B"] 0 ["B"]) ; 0
到目前为止一切正常,但如果我尝试使用函数调用传递前任:
(match2 ["B"] 0 ((fn [] ["B"]))) ; AssertionError Invalid list syntax [] in (fn [] ["B"])
问题是因为match2是一个宏clojure不会评估函数调用,并且只会按原样传递表单。然后,未评估的形式转到core.match(再次未评估,因为core.match本身就是一个宏),core.match抛出异常,因为表单不正确。
如何强制评估宏观参数?或任何其他解决方法?
我被暗示这通常是用第二个宏来完成的,但我的尝试没有产生好结果。
答案 0 :(得分:2)
我看到两个选项。在宏中使用eval。
或者,您可以让宏不调用匹配宏。让它调用另一个调用匹配宏的函数。这将迫使评估途中匹配。
以下是阅读此类问题的好文章:
http://amalloy.hubpages.com/hub/Clojure-macro-writing-macros
答案 1 :(得分:-1)
core.match
是一个编译器。它将一些表单转换为可执行表达式。它可以处理的表单必须遵循语法,因此断言抛出。作为一个宏,它编译在...编译时。无论你怎么努力,你都不能让它编译运行时表达式的结果。
即使你设法在编译时对(fn [] ["B"])
进行评估,以便将值提供给match
,这也不是我认为的目标。您尝试做的是将匹配与您的程序逻辑评估的表达式匹配。在那里,很遗憾地说core.match
是不可能的,D。Nolen证实了这一点。
尽管如此,matchure
可以做到这一点:在运行时创建匹配函数/表达式,请参阅fn-match
。它是无法维护的AFAIK,但只是起作用。我前段时间修补了它使用clj 1.6,here。