如何使用Clojure - >具有内在功能的宏

时间:2013-11-26 13:57:20

标签: clojure

我是Clojure初学者,我想了解->

此代码有效:

(-> '(1 2 3) reverse)

但是这甚至没有编译,我不知道如何处理错误信息:

user=> (-> '(1 2 3) (fn [x] (reverse x)))

CompilerException java.lang.IllegalArgumentException:参数声明引用应该是一个向量,编译:(NO_SOURCE_PATH:1:1)

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:6)

当意想不到的事情开始发生时,我会使用macroexpand和朋友。如果你在这里使用它们,那么发生的事情就变得非常明显了。

user=> (macroexpand-1 '(-> '(1 2 3) (fn [x] (reverse x))))
(fn (quote (1 2 3)) [x] (reverse x))

我认为看到这一点很明显(quote (1 2 3)不应该是fn的第一个arg。

我们还可以看到丑陋的双重方法解决了这个问题:

user=> (macroexpand-1 '(-> '(1 2 3) ((fn [x] (reverse x)))))
((fn [x] (reverse x)) (quote (1 2 3)))

附带说明让我失望:你必须使用macroexpand-1来获得结果。如果你使用macroexpandclojure.walk/macroexpand-all它会在第一次扩展后爆炸(除了你的例外),因为fn本身就是一个宏,并且在第一次调用之后被调用了错误的语法扩展