petermash
petermash

Reputation: 11

Casting an ArraySeq as an IFn

Elementary question here.. I am a little confused.

(((fn [_ & y] y) 'blah +) 3 4)

will result in the error:

"java.lang.ClassCastException: clojure.lang.ArraySeq cannot be cast to clojure.lang.IFn"

I was rather hoping for it to be evaluated to:

(+ 3 4) 

which equals 7.

I see that

((fn [_ & y] y) 'blah +)

evaluates to

(#<core$_PLUS_ clojure.core$_PLUS_@7cd07b83>)

which is an ArraySeq, not an IFn; so I understand the error- however I am not sure why it doesn't just evaluate to a + instead.

Upvotes: 1

Views: 217

Answers (2)

noisesmith
noisesmith

Reputation: 20194

& puts all excess arguments in a collection. This can be destructured to access its first element:

user> (((fn [_ & [y & _]] y) 'blah +) 3 4)
7

or, equivalently,

user> (((fn [_ & ys] (first ys)) 'blah +) 3 4)
7

Upvotes: 3

mike3996
mike3996

Reputation: 17537

The ampersand & in function argument destruction collects all remaining arguments to a seq, even if there is only one there.

user=> ((fn [_ & y] y) 'blah +)
(#<core$_PLUS_ clojure.core$_PLUS_@205074de>)
user=> ((fn [_ y] y) 'blah +)
#<core$_PLUS_ clojure.core$_PLUS_@205074de>

Upvotes: 1

Related Questions