Mark Needham

Thoughts on Software Development

Clojure: Anonymous functions using short notation and the ‘ArityException Wrong number of args (0) passed to: PersistentVector’

with one comment

In the time I’ve spent playing around with Clojure one thing I’ve always got confused by is the error message you get when trying to return a vector using the anonymous function shorthand.

For example, if we want function which creates a vector with the values 1, 2, and the argument passed into the function we could write the following:

> ((fn [x] [1 2 x]) 6)
[1 2 6]

However, when I tried to convert it to the shorthand ‘#()’ syntax I got the following exception:

> (#([1 2 %]) 6)
clojure.lang.ArityException: Wrong number of args (0) passed to: PersistentVector
                                      AFn.java:437 clojure.lang.AFn.throwArity
                                       AFn.java:35 clojure.lang.AFn.invoke
                                  NO_SOURCE_FILE:1 user/eval575[fn]
                                  NO_SOURCE_FILE:1 user/eval575

On previous occasions I’ve just stopped there and gone back to the long hand notation but this time I wanted to figure out why it didn’t work as I expected.

I came across this StackOverflow post which explained the way the shorthand gets expanded:

#() becomes (fn [arg1 arg2] (...))

which means that:

#(([1 2 %]) 6) becomes ((fn [arg] ([1 2 arg])) 6)

We are evaluating the vector [1 2 arg] as a function but aren’t passing any arguments to it. One way it can be used as a function is if we want to return a value at a specific index e.g.

> ([1 2 6] 2)
6

We don’t want to evaluate a vector as a function, rather we want to return the vector using the shorthand syntax. To do that we need to find a function which will return the argument passed to it and then pass the vector to that function.

The identity function is one such function:

> (#(identity [1 2 %]) 6)
[1 2 6]

Or if we want to be more concise the thread-first (->) works too:

> (#(-> [1 2 %]) 6)
[1 2 6]
Be Sociable, Share!

Written by Mark Needham

September 23rd, 2013 at 9:42 pm

Posted in Clojure

Tagged with

  • A more semantically equivalent way of doing it is this:

    > (#(vector 1 2 %) 6)

    I say “semantically” because “[a b c]” is really just syntactic sugar for “(vector a b c)”