为什么匿名函数定义语法不同?

Why the difference in anonymous function definition syntax?

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

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

但是->宏不接受这样的匿名函数。假设我想加 10 然后乘以 2。我会尝试写:

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

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

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

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

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

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

(fn [x] (+ 10 x))

例如

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

会 return 是这样的:

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

第二部分。当您使用线程宏时,如 docs say,宏通过将第一个参数作为 第二项 插入到第一个表单中来展开。如果有更多表格,则将第一个表格作为 第二项 插入第二个表格,依此类推。

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

因此,当您使用

时,要结合这两点
(-> 5 #(+ 10 %) #(* 2 %))

按照规则,它被扩展成功能类似于此的东西

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

无法编译。

此外,作为旁注,形式 (+ 10) 不是匿名函数。这是一个部分函数调用,在宏扩展期间使用参数进行更新。 'partial',我的意思是字面意义上的,而不是函数式编程意义上的。

更新

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

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

会产生等同于

的功能
((fn [x] (+ 10 x)))

所以,当一个项目被插入到它的 第二个 位置时,它看起来像

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

相当于

(#(+ 10 %) 5)