What is the difference between fn an defn in clojure?
defn
is basically defined as*:
(defmacro defn [name args & body]
`(def ~name (fn ~args ~@body)))
Or in other words, you could basically write:
(defn my-func [a]
(stuff a))
As*:
(def my-func
(fn [a] (stuff a)))
Using just fn
creates an anonymous function that alone isn't bound to any symbol externally. It must be bound using let
or def
to be referred to outside of itself.
By having defn
defined in terms of def
and fn
, the responsibilies of binding a function to a symbol (as well as all the other complexities that come with it) and handling function behaviour can be separated.
When you supply a name for fn
, it can't be referred to outside of the function, but it can be used to refer to itself to create a recursive anonymous function:
(fn my-func [n] (my-func (inc n))
And, it gives the function a slightly nicer name to show up in stack traces to ease debugging:
(defn my-func []
((fn my-inner-func [] (/ 1 0))))
=> #'digital-rain.core/my-func
(my-func)
java.lang.ArithmeticException: Divide by zero
at clojure.lang.Numbers.divide(Numbers.java:158)
at clojure.lang.Numbers.divide(Numbers.java:3808)
at digital_rain.core$my_func$my_inner_func__2320.invoke(form-init1838550899342340522.clj:2)
at digital_rain.core$my_func.invokeStatic(form-init1838550899342340522.clj:2)
at digital_rain.core$my_func.invoke(form-init1838550899342340522.clj:1)
*
These are gross understatements and a tad misleading, but they simplify things.
In reality, defn
isn't defined using defmacro
; defmacro
is actually defined using defn
. defn
also adds some good stuff like pre/post condition checking, documentation, and other meta information; but that's not as relevant here. I recommend looking over its source for a more in-depth look; although it's pretty convoluted. The fundamental guts of clojure.core
can be a little daunting to wrap your head around.