13

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.

Eric Wilson
  • 57,719
  • 77
  • 200
  • 270

3 Answers3

21

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.
mikera
  • 105,238
  • 25
  • 256
  • 415
  • 1
    Another limitation worth mentioning (I didn't know if I could/should edit your response) is that `fn` allows you to name your function, so that they can be referenced within the body, as in: `(def fact (fn f [x] (if (= 1 x) 1 (* x (f (dec x))))))` – Gabriel Mitchell Oct 02 '12 at 02:26
  • Really appreciate the `comp` and `partial` suggestions. I wondered if those were present, having appreciated them in Haskell. – Eric Wilson Oct 02 '12 at 13:32
5

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.

Community
  • 1
  • 1
brianpeiris
  • 10,735
  • 1
  • 31
  • 44
2

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 %&).

Community
  • 1
  • 1
Giuliani Sanches
  • 650
  • 5
  • 20