Eric Wilson
Eric Wilson

Reputation: 59395

Is there a difference between the fn and # syntax for anonymous functions in Clojure?

I'm new to clojure, and I've seen anonymous functions written like:

(fn [x] (* x x))

and also like:

#(* % %)

Obviously, the second is more concise. Is there any relevant difference? Can every anonymous function be represented in either style? Is one more idiomatic?

Related to this question, I was unable to determine how to convert (fn [x] [x x]) to the latter syntax. I would appreciate a pointer to documentation that clarifies this situation.

Upvotes: 13

Views: 1033

Answers (3)

mikera
mikera

Reputation: 106391

The most important differences are:

  • (fn ...) can be nested, #() cannot
  • You can name your parameters better with (fn [x y] ..) or similar, rather than using %, %2, %3 etc.
  • You can name a function with (fn ...) for recursive usage, e.g. (fn fib [n] (if (<= n 1) 1 (+ (fib (- n 1)) (fib (- n 2)))))
  • It's easier to do code generation/manipulation (fn [...] ...) since #() is a reader macro rather than a regular Clojure form.
  • #() is more concise. But if that is a major consideration, you probably have your priorities wrong :-)

Personally my advice would be:

  • Prefer (fn [...] ...) in most circumstances
  • Use #() only for very short inline functions, e.g. (map #(+ 2 %) (range 10))
  • Also consider that it may be better to generate anonymous functions via higher-order functions rather than writing them out explicitly e.g. (comp func1 func2) or (partial func param1 param2) etc.

Upvotes: 21

brianpeiris
brianpeiris

Reputation: 10795

Another SO answer (Common programming mistakes for Clojure developers to avoid) mentions that #([% %]) expands to fn [%] ([% %]) (note the parentheses), which causes an ArityException.

You can do #(vector % %) to workaround this limitation.

Upvotes: 5

Giuliani Sanches
Giuliani Sanches

Reputation: 672

From the docs, i think that these are the most relevant differences:

idiomatic used would be for very short one-off mapping/filter fns and the like.

#() forms cannot be nested.

Another thing is that if you need named parameters, fn is a better option. For the #() you will use % or, for more the one parameters, something like %1, %2 and so on (also %&).

Upvotes: 2

Related Questions