我们可以这样定义和使用匿名函数:

repl=> (#(+ 10 %) 1)
11


但是->宏将不接受此类匿名函数。假设我要加10,然后乘以2。我尝试写:

(-> 5 #(+ 10 %) #(* 2 %))


但是由于某些原因,这不是正确的代码,正确的代码是

(-> 5 (+ 10) (* 2))


(+ 10)#(+ 10 %)有什么区别,为什么->宏不能接受用#()定义的匿名函数?

最佳答案

这是我的解释尝试。有两个部分。

首先,匿名文字语法。编写#(+ 10 %)时,它会扩展为功能类似于以下内容的内容:

(fn [x] (+ 10 x))


对于前。

=> (macroexpand '(#(+ 10 %))


将返回类似:

(fn* [p1__7230#] (+ 10 p1__7230#))


第二部分。当您使用线程宏作为docs say时,宏会通过将第一个参数作为第二项插入第一种形式来扩展。并且如果还有更多表格,则将第二个表格中的第一个表格作为第二个项目插入,依此类推。

这里的关键是第二项。它并不在乎您提供什么形式的参数,它只会使用该规则进行扩展。

因此,当您使用时要结合这两点

(-> 5 #(+ 10 %) #(* 2 %))


遵循规则,它被扩展为功能类似于此的东西

(fn (fn 5 [x] (+ 10 x)) [y] (* 2 y))


不会编译。

另外,请注意,(+ 10)格式不是匿名函数。这是一个局部函数调用,在宏扩展过程中会使用参数进行更新。所谓“部分”,是指字面意义,而不是功能编程意义。

更新资料

为了解释当您将匿名文字括在括号中时(如对问题的评论所述),为什么它起作用,您可以从这两个规则推断出结果。对于前。

 => (macroexpand '(#(+ 10 %)))


将导致功能等效

((fn [x] (+ 10 x)))


因此,当一个项目插入第二个位置时,它看起来像

((fn [x] (+ 10 x)) 5)


相当于

(#(+ 10 %) 5)

关于clojure - 为什么匿名函数定义语法不同?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32836705/

10-14 04:14