Clojure 评估宏的参数
Clojure evaluate argument of macro
我正在尝试编写一个为 core.match 宏生成模式的宏。
(defmacro match2
[state i predecessor]
`(match ~[state]
[(~(vec (concat (repeat i '_)
predecessor
'(& r)))
:seq)] ~i
:else false))
如果我直接将它与硬编码 predecessor:
一起使用,效果很好
(match2 ["B"] 0 ["B"]) ; 0
到目前为止一切都很好,但是如果我尝试使用函数调用传递 predecessor:
(match2 ["B"] 0 ((fn [] ["B"]))) ; AssertionError Invalid list syntax [] in (fn [] ["B"])
问题在于,因为 match2 是一个宏,clojure 不会评估函数调用,只会按原样传递表单。未计算的形式然后转到 core.match(再次未计算,因为 core.match 本身是一个宏)并且 core.match 抛出异常,因为形式不是正确的模式。
如何强制对宏参数求值?或者任何其他解决方法?
我被暗示这通常是用第二个宏完成的,但我的尝试没有产生好的结果。
我看到两个选项。在您的宏中使用 eval。
或者,您可以让您的宏不调用匹配宏。让它调用另一个调用匹配宏的函数。这将强制评估途中匹配。
这里有一篇关于此类问题的好文章:
http://amalloy.hubpages.com/hub/Clojure-macro-writing-macros
core.match
是一个编译器。它将一些形式变成可执行的表达式。它可以处理的形式必须遵守语法,因此断言抛出。作为一个宏,它在……编译时编译。无论您多么努力,都无法让它编译运行时表达式的结果。
即使您设法在编译时评估 (fn [] ["B"])
以便将值提供给 match
,我认为这不是您的目标。您要做的是将匹配项与您的程序逻辑评估的表达式进行匹配。去过那里,很遗憾地说 core.match
是不可能的,D. Nolen 证实了这一点。
不过,matchure
可以做到这一点:在运行时创建匹配函数/表达式,请参阅 fn-match
. It is unmaintained AFAIK but just works. I've patched it some time ago to use clj 1.6, here。
我正在尝试编写一个为 core.match 宏生成模式的宏。
(defmacro match2
[state i predecessor]
`(match ~[state]
[(~(vec (concat (repeat i '_)
predecessor
'(& r)))
:seq)] ~i
:else false))
如果我直接将它与硬编码 predecessor:
一起使用,效果很好(match2 ["B"] 0 ["B"]) ; 0
到目前为止一切都很好,但是如果我尝试使用函数调用传递 predecessor:
(match2 ["B"] 0 ((fn [] ["B"]))) ; AssertionError Invalid list syntax [] in (fn [] ["B"])
问题在于,因为 match2 是一个宏,clojure 不会评估函数调用,只会按原样传递表单。未计算的形式然后转到 core.match(再次未计算,因为 core.match 本身是一个宏)并且 core.match 抛出异常,因为形式不是正确的模式。
如何强制对宏参数求值?或者任何其他解决方法?
我被暗示这通常是用第二个宏完成的,但我的尝试没有产生好的结果。
我看到两个选项。在您的宏中使用 eval。
或者,您可以让您的宏不调用匹配宏。让它调用另一个调用匹配宏的函数。这将强制评估途中匹配。
这里有一篇关于此类问题的好文章:
http://amalloy.hubpages.com/hub/Clojure-macro-writing-macros
core.match
是一个编译器。它将一些形式变成可执行的表达式。它可以处理的形式必须遵守语法,因此断言抛出。作为一个宏,它在……编译时编译。无论您多么努力,都无法让它编译运行时表达式的结果。
即使您设法在编译时评估 (fn [] ["B"])
以便将值提供给 match
,我认为这不是您的目标。您要做的是将匹配项与您的程序逻辑评估的表达式进行匹配。去过那里,很遗憾地说 core.match
是不可能的,D. Nolen 证实了这一点。
不过,matchure
可以做到这一点:在运行时创建匹配函数/表达式,请参阅 fn-match
. It is unmaintained AFAIK but just works. I've patched it some time ago to use clj 1.6, here。