Clojure评估宏的论点

时间:2015-09-28 22:47:31

标签: clojure macros pattern-matching core.match

我正在尝试编写一个为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抛出异常,因为表单不正确。

如何强制评估宏观参数?或任何其他解决方法?

我被暗示这通常是用第二个宏来完成的,但我的尝试没有产生好结果。

2 个答案:

答案 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