Consider the following function:
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
Why is the argument list a clojure.lang.ArraySeq
and not something much more common like a PersistentVector
? Or why doesn't ArraySeq
implement IFn
? Performance reasons? Seems like you have to know the underlying implementation of things a bit while doing Clojure. Feel free to enlighten me.
PS: this question is not about "is this idiomatic or not?" Just asking why this is like it is.
(defn first-args [& args]
(first args))
(apply first-args (range))
;=> 0
You can apply a function to an infinite argument sequence, consuming items only as needed. If &
args were required to be a vector (or anything more concrete than an ISeq), this would be impossible.
As for why seqs aren't callable: it would encourage using them in a way that performs very poorly.
Other answers are already good, but just wanted to present an alternative to achieve the same effect:
(defn first-args [first-arg & others]
first-arg)
(first-args 1 2 3)
=> 1
i.e. you can explicitly name the first argument in the function definition.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With