· clojure

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

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 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 http://clojuredocs.org/clojure_core/clojure.core/identity function is one such function:

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

Or if we want to be more concise the http://clojuredocs.org/clojure_core/clojure.core/-%3E works too:

> (#(-> [1 2 %]) 6)
[1 2 6]
  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket