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

gvl*_*sov 2 clojure anonymous-function function-composition

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

repl=> (#(+ 10 %) 1)
11
Run Code Online (Sandbox Code Playgroud)

->宏不会接受这样的匿名功能.假设我想添加10然后乘以2.我会尝试写:

(-> 5 #(+ 10 %) #(* 2 %))
Run Code Online (Sandbox Code Playgroud)

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

(-> 5 (+ 10) (* 2))
Run Code Online (Sandbox Code Playgroud)

(+ 10)和之间的区别是什么#(+ 10 %),为什么不->接受宏定义的匿名函数#()

Bha*_*ikh 5

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

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

(fn [x] (+ 10 x))
Run Code Online (Sandbox Code Playgroud)

对于前者

=> (macroexpand '(#(+ 10 %))
Run Code Online (Sandbox Code Playgroud)

会返回类似的东西:

(fn* [p1__7230#] (+ 10 p1__7230#))
Run Code Online (Sandbox Code Playgroud)

第二部分.当你使用线程宏时,正如文档所说,宏通过将第一个参数作为第二个项插入第一个表单来扩展.如果有更多表单,请将第一个表单作为第二个表单插入 第二个表单,依此类推.

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

所以,当你使用时,要结合两个点

(-> 5 #(+ 10 %) #(* 2 %))
Run Code Online (Sandbox Code Playgroud)

按照规则,它会扩展为功能上与此类似的东西

(fn (fn 5 [x] (+ 10 x)) [y] (* 2 y))
Run Code Online (Sandbox Code Playgroud)

哪个不编译.

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

更新

要解释为什么它将括号中的匿名文字括起来时(如对问题的评论所述),您可以推断出这两个规则的结果.对于前者

 => (macroexpand '(#(+ 10 %)))
Run Code Online (Sandbox Code Playgroud)

会导致功能相当于

((fn [x] (+ 10 x)))
Run Code Online (Sandbox Code Playgroud)

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

((fn [x] (+ 10 x)) 5)
Run Code Online (Sandbox Code Playgroud)

这相当于

(#(+ 10 %) 5)
Run Code Online (Sandbox Code Playgroud)

  • 我不会使用`macro-expand`来演示读者语法(`#(..)`是).您甚至可以使用前一个阶段:`(read-string"#(foo%)")`. (3认同)