匿名功能简写

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来实际调用它是有点愚蠢的.