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

Clojure 为什么匿名函数定义语法不同?,clojure,anonymous-function,function-composition,Clojure,Anonymous Function,Function Composition,我们可以定义并使用如下匿名函数: repl=> (#(+ 10 %) 1) 11 但是->宏不接受这种匿名函数。假设我想加10,然后乘以2。我试着写: (-> 5 #(+ 10 %) #(* 2 %)) 但由于某些原因,这不是正确的代码,正确的代码是 (-> 5 (+ 10) (* 2)) (+10)和#(+10%)之间有什么区别,为什么->宏不接受用#()定义的匿名函数?下面是我的解释。有两部分 首先,匿名文字语法。当您编写#(+10%)时,它会被扩展为功能类似于以下内

我们可以定义并使用如下匿名函数:

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#))
第二部分。使用threading宏作为时,宏会通过将第一个参数作为第二项插入第一个表单来展开。如果有更多表单,则在第二个表单中插入第一个表单作为第二项,依此类推

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

因此,当您使用

(-> 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)

请注意,放置
%
表示更好地使用
->
(最后一个线程)。它对
+
*
没有区别,但可以与其他函数一起使用。您也可以在线程宏中“调用”您的
#()
,使其工作:
(>5(#(+10%))(#(*2%))
我不会使用
宏扩展来演示读卡器语法(这是
#(…)
)。甚至可以使用更早的阶段:
(读取字符串“#(foo%)”)