为什么参数列表为ArraySeq?

时间:2011-11-20 22:19:35

标签: clojure arguments

考虑以下功能:

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:这个问题不是“这是否是惯用的?”只是问为什么会这样。

3 个答案:

答案 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(如列表)。