我正在尝试编写一个为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抛出异常,因为表单是不正确的模式。
如何在宏观论证上强制进行评估?或者其他的解决办法?
我被暗示这通常是用第二个宏完成的,但是我的尝试没有取得好的结果。
发布于 2015-09-29 15:59:02
core.match是一个编译器。它将一些表单转换为可执行表达式。它可以处理的表单必须遵守语法,从而引发断言。作为一个宏,它编译在..。编译时间。无论您如何努力,都不能让它编译运行时表达式的结果。
即使您设法在编译时对(fn [] ["B"])进行评估,以便将该值提供给match,但我认为这不是您的目标。您想要做的是与程序逻辑计算的表达式进行匹配。在那里,抱歉地说core.match是不可能的,诺伦证实了这一点。
尽管如此,matchure还是可以这样做的:在运行时创建匹配函数/表达式,参见fn-match。这是未维护的AFAIK,但只是工作。一段时间前,我对它进行了修补,以便使用CLJ1.6,这里。
发布于 2015-09-28 23:09:41
我有两种选择。在宏中使用eval。
或者,您可以让宏不调用match宏。让它调用另一个函数,该函数调用匹配宏。这将迫使评估在途中匹配。
下面是一篇关于这类问题的好文章:
http://amalloy.hubpages.com/hub/Clojure-macro-writing-macros
https://stackoverflow.com/questions/32832982
复制相似问题