为什么匿名函数定义语法不同?
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)
我们可以这样定义和使用匿名函数:
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)