匿名函数简写

有一些我不明白匿名函数使用短符号#(..)

以下工作:

REPL> ((fn [s] s) "Eh") "Eh" 

但是这不是:

 REPL> (#(%) "Eh") 

这工作:

 REPL> (#(str %) "Eh") "Eh" 

我不明白的是为什么(#(%)“Eh”)不起作用,同时我也不需要用str ((fn [s] s))“Eh”)

它们都是匿名函数,在这里它们都是一个参数。 为什么速记符号需要一个函数,而另一个符号不需要?

 #(...) 

是速记

 (fn [arg1 arg2 ...] (...)) 

(argN的数量取决于你在体内有多less%N)。 所以当你写:

 #(%) 

它被翻译成:

 (fn [arg1] (arg1)) 

请注意,这与您的第一个匿名函数有所不同,如下所示:

 (fn [arg1] arg1) 

您的版本将arg1作为值返回,扩展速记所带来的版本会尝试将其作为函数调用。 你得到一个错误,因为一个string不是一个有效的函数。

由于简写在身体周围提供了一组括号,因此只能用于执行单个函数调用或特殊forms。

由于其他答案已经很好的指出了,你发布的#(%)实际上扩展到了(fn [arg1] (arg1)) ,这与(fn [arg1] arg1)

@John Flatness指出,你可以使用identity ,但是如果你正在寻找使用#(...) dispatchmacros写identity方法,你可以这样做:

 #(-> %) 

通过将#(...) dispatchmacros与->线程macros相结合,它将被扩展为(fn [arg1] (-> arg1)) ,它又扩展到(fn [arg1] arg1)想要你想要的。 我也发现->#(...)macros组合有助于编写返回向量的简单函数,例如:

 #(-> [%2 %1]) 

当你使用#(...) ,你可以想象你正在写(fn [args] (...))包括刚刚在英镑之后开始的圆括号。

所以,你的非工作的例子转换为:

 ((fn [s] (s)) "Eh") 

这显然不起作用,因为你试图调用string“呃”。 你的例子用str工作,因为现在你的函数是(str s)而不是(s)(identity s)会更接近你的第一个例子,因为它不会被强迫。

如果你仔细想一下,这是有道理的,因为除了这个最简单的例子之外,每个匿名函数都会调用一些东西 ,所以要求另外一个嵌套的parens实际地调用它会有点愚蠢。