Clojure's - >和 - >>宏

时间:2014-07-14 00:41:20

标签: macros clojure operators

Clojure的->>宏线程来自最后一个参数的表单,当->从第一个参数形成时。

user=> (->> a (+ 5) (let [a 5]))
10

但是,当我使用交换的操作时,我得到一个例外。

user=> (-> a (let [a 5]) (+ 5))

CompilerException java.lang.IllegalArgumentException: let requires a vector for its binding in user:1, compiling:(NO_SOURCE_PATH:1:7) 

此外,我希望这两个操作会得到相同的结果,但事实并非如此。

user=> (-> 0 (Math/cos) (Math/sin))
0.8414709848078965
user=> (->> 0 (Math/sin) (Math/cos))
1.0

怎么了? ->->>宏的工作原理是什么?

1 个答案:

答案 0 :(得分:5)

->宏将参数作为给定函数的第一个参数插入,而不是将参数赋给最后一个函数。 同样,->>作为最后一个参数插入。

user=> (macroexpand '(-> x (- 1)))
(- x 1)
user=> (macroexpand '(->> x (- 1)))
(- 1 x)

两个简单的例子:

user=> (-> 1 (- 1) (- 2)) 
-2
user=> (->> 1 (- 1) (- 2))
2

至于第一个示例,-2 == (- (- 1 1) 2)和第二个2 == (- 2 (-1 1))

结果,我们得到了一元函数的相同结果。

user=> (macroexpand '(-> 0 Math/sin Math/cos))
(. Math cos (clojure.core/-> 0 Math/sin))
user=> (macroexpand '(->> 0 Math/sin Math/cos))
(. Math cos (clojure.core/->> 0 Math/sin))

因此,只有->>才有意义。

user=> (macroexpand '(->> a (+ 5) (let [a 5])))
(let* [a 5] (clojure.core/->> a (+ 5)))
user=> (macroexpand '(-> a (+ 5) (let [a 5])))

IllegalArgumentException let requires a vector for its binding in user:1  clojure.core/let (core.clj:4043)