[编辑,因为回答中缺少#]
由于 constantly
的意图是允许任意参数的函数始终返回一个常数,所以这种做法有点笨拙。#(...) 匿名函数缩写提供了快速定义匿名函数的简便方法,这些函数根据不同的参数数量工作。
0 - #(vector)
1 - #(vector %1)
2 - #(vector %1 %2)
...
n - #(vector %1 %2 ... %n)
& args - #(apply vector %&)
不过,有一些限制,因为你在定义函数体……如果你试图定义类似 identity 的东西,它最终会看起来像一个调用。
#(%)
;;这会尝试将单个参数作为一元函数调用。
一种解决方案是使用 let 或其他形式绑定输入,以传达参数数量或参数的元数……
#(let [v %] v)
或
#(do %)
将正常工作,就像 identity 一样,我们只是在体中返回它。
但是,我们希望定义一个可变参数的函数,所以我们想要 %& 表示参数。然而,参数对于结果来说是无意义的……唯一的含义是向匿名函数糖传达参数的数量或参数的元数。
虽然有些awkward,但这是其中一种方法。
(defn constantly2 [v]
;;ignore the arguments, but communicate a varargs function
#(let [_ %&]
v))
user=> (def f (constantly2 10))
#'user/f
user=> (f 1 2 3 4)
10
user=> (f 1)
10
user=> (f 5)
10
user=> (f :a)
10
我可能不会使用这种 #(..) 语法糖来处理这类事情。这种简写对于非常简单的内联匿名函数最有用,即便如此,我还是通常更倾向于明确写出 fn
。