考虑以下功能:
user> (defn first-args [& args]
(args 0))
#'user/first-args
user> (first-args 1 2 3) ;=> clojure.lang.ArraySeq cannot be cast to clojure.lang.IFn
为什么参数列表为clojure.lang.ArraySeq
而不是像PersistentVector
那样更常见?或者为什么不ArraySeq
实施IFn
?表现原因?看起来你在做Clojure时必须知道一些事情的基本实现。随意赐教。
PS:这个问题不是“这是否是惯用的?”只是问为什么会这样。
答案 0 :(得分:23)
(defn first-args [& args]
(first args))
(apply first-args (range))
;=> 0
您可以将函数应用于无限参数序列,仅在需要时使用项目。如果&
args需要是一个向量(或者比ISeq更具体的东西),那就不可能了。
至于为什么seqs不可调用:它会鼓励以非常糟糕的方式使用它们。
答案 1 :(得分:4)
其他答案已经很好,但只是想提出一个替代方案来达到同样的效果:
(defn first-args [first-arg & others]
first-arg)
(first-args 1 2 3)
=> 1
即。您可以在函数定义中明确命名第一个参数。
答案 2 :(得分:0)
您正在调用args
作为第2行中的函数。您想要的实际上是:
(defn first-args [& args]
(first args))
ArraySeq实际上比Vector更“常见”,因为Vector继承了ISeq。这就是为什么你不能在这里做(get args 0)
,这似乎是你想要调用的,因为它只适用于地图和矢量,而不适用于任何ISeq(如列表)。