When I was first learning Clojure, I found the shorthand syntax for anonymous functions to be a bit confusing. Hopefully this little write up on the different ways to define functions will help someone out. If you're just looking for a refresher on the anonymous function shorthand, skip right to the bottom.
If you're spent some time with Clojure, it's likely that you're familiar with the standard function definition:
(defn my-func [arg1 arg2] (... function body here ...))
Which is a shorthand for
(def my-func (fn [arg1 arg2] (... function body here ...)))
You can easily make a non-public function by using defn-
(defn- my-func [arg1 arg2] (... function body here ...))
You've already seen the basic anonymous function definition in the second example above.
(fn [arg1 arg2] (... function body here ...))
This function is anonymous because it's not bound to a particular name using def. This definition alone isn't very useful: it needs context.
A simple example, concatenating the two arguments into a single string. You could do something like this:
((fn [arg1 arg2] (str arg1 arg2)) "A" "B")
Because of the outermost parentheses the anonymous function is executed immediately and passed the two arguments "A" and "B", ultimately returning "AB"
This still isn't a very practical example. In Clojure, you'll often see anonymous functions passed as arguments to other functions. In the case of the
map function, it accepts a function as its first argument and a collection as its second. That function argument doesn't need to be a language defined function or a user defined function, it can be anonymous. You could do something like this:
(map (fn [arg1] (str "Hello: " arg1)) ["A" "B"])
map function applies the anonymous function to each element in the collection
["A" "B"] and returns
("Hello: A" "Hello: B")
That's a relatively simple anonymous function, but you can probably see that it's already getting a bit hard to read. Enter the shorthand syntax for anonymous functions. Let's reproduce the last anonymous function using the shorthand syntax.
#(str "Hello: " %)
It's a lot less verbose than the original, but it's also not completely intuitive. Let's break it down. The
#() syntax is what tells Clojure that this is a function. It's pretty much equivalent to
(fn  ()).
% symbol is used as a shorthand to reference the arguments passed to the function, so that you don't clutter the function definition by explicitly naming them. Both
%1 will reference the first argument passed in,
%2 will reference the second argument, and so on.
#(str "Hello: " %) is the same as
(fn [arg1] (str "Hello: " arg1))
Clojure will pay attention to how many arguments your shorthand anonymous function is expecting and complain if it receives the wrong number of arguments. For example:
(#(str "Hello:" % " and " %2) "A")
This function expects 2 arguments, but receives only one, causing Clojure to say:
ArityException Wrong number of args (1) passed to: user$eval740$fn clojure.lang.AFn.throwArity (AFn.java:437)