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.

Tags:

Clojure