Ced*_*tin 84 function clojure anonymous-function
使用短符号#(..)有一些我不了解匿名函数的东西
以下作品:
REPL> ((fn [s] s) "Eh")
"Eh"
Run Code Online (Sandbox Code Playgroud)
但这不是:
REPL> (#(%) "Eh")
Run Code Online (Sandbox Code Playgroud)
这有效:
REPL> (#(str %) "Eh")
"Eh"
Run Code Online (Sandbox Code Playgroud)
我不明白的是为什么(#(%)"Eh")不起作用,同时我不需要使用str in ((fn [s] s)"Eh")
它们都是匿名函数,它们都带有一个参数.为什么简写符号需要一个函数而另一个符号不需要?
Bar*_*mar 124
#(...)
Run Code Online (Sandbox Code Playgroud)
是简写
(fn [arg1 arg2 ...] (...))
Run Code Online (Sandbox Code Playgroud)
(其中argN的数量取决于你体内有多少%N).所以当你写:
#(%)
Run Code Online (Sandbox Code Playgroud)
它被翻译成:
(fn [arg1] (arg1))
Run Code Online (Sandbox Code Playgroud)
请注意,这与您的第一个匿名函数不同,它类似于:
(fn [arg1] arg1)
Run Code Online (Sandbox Code Playgroud)
您的版本返回arg1作为值,扩展速记的版本尝试将其称为函数.您收到错误,因为字符串不是有效的函数.
由于速记在身体周围提供一组括号,因此它只能用于执行单个函数调用或特殊形式.
Dao*_*Wen 63
正如其他答案已经非常好地指出的那样,#(%)
你发布的内容实际上扩展到类似的东西(fn [arg1] (arg1))
,这与它完全不同(fn [arg1] arg1)
.
@John Flatness指出你可以使用identity
,但如果你正在寻找一种写作方式identity
使用#(...)
dispatch宏方法,你可以这样做:
#(-> %)
Run Code Online (Sandbox Code Playgroud)
通过将#(...)
调度宏与->
线程宏相结合,它会扩展为类似的东西(fn [arg1] (-> arg1))
,再次扩展到(fn [arg1] arg1)
,这只是你想要的.我也找到了->
和#(...)
宏组合有助于编写返回向量的简单函数,例如:
#(-> [%2 %1])
Run Code Online (Sandbox Code Playgroud)
Joh*_*ess 20
当你使用时#(...)
,你可以想象你正在写作(fn [args] (...))
,包括你在英镑之后开始的括号.
所以,你的非工作示例转换为:
((fn [s] (s)) "Eh")
Run Code Online (Sandbox Code Playgroud)
这显然不起作用,因为你试图调用字符串"Eh".你的例子str
有效,因为现在你的功能(str s)
不是(s)
.(identity s)
会比你的第一个例子更接近,因为它不会强迫str.
如果你考虑它是有道理的,因为除了这个完全最小的例子之外,每个匿名函数都会调用某些东西,所以要求另一套嵌套的parens来实际调用它是有点愚蠢的.