liveBook · Manning

Defn

As explained in Clojure: The Essential Reference

defn is a Clojure macro that defines a named function and interns it in the enclosing namespace.

Use `defn` to give a Clojure function a name that can be called and composed with other functions. It is a macro: it builds a function using `fn` and interns the name in the current namespace using `def`. Use `defn-` for a private definition. section 2.1 section 2.1.1

A single-arity function

`(defn hello [person] (str "hello " person))` defines a function of one argument. `(hello "people")` returns `"hello people"`. A docstring can go between the name and argument vector; `clojure.repl/doc` and the function's Var metadata can then expose it. section 2.1.1

The declaration can do more than name arguments:

  • Provide separate bodies for multiple arities, or destructure arguments. section 2.1.1
  • Attach metadata to the definition or an argument list. A `^:bench` tag can identify public functions for a profiling wrapper. section 2.1.1
  • Add `:pre` and `:post` conditions to check inputs and results. Failed checks in the `save!` example produce test failures and assertion errors. section 2.1.1
  • Add type hints where Java calls otherwise produce reflection warnings; the HMAC-signing example shows both the warnings and a timed run after hints are added. section 2.1.1

The declaration grammar is broad, but not unlimited: the illustrated attempt to define a function with 21 parameters fails with a compiler error stating that more than 20 parameters cannot be specified. section 2.1.1

(macroexpand  ; #1
  '(defn hello [person]
      (str "hello " person)))

;; (def hello
;;   (clojure.core/fn ; #2
;;     ([person] (str "hello " person))))

(hello "people") ; #3

;; "hello people"

The expansion makes the relationship among `defn`, `def`, and `fn` concrete, alongside the greeting's result. section 2.1.1

(defn ^<metamap>? <name> fdecl)

  fdecl :=> <docstring>? <metamap>? arities <metamap>?

  arities :=> ^<metamap>? [arity] body
              OR
              (^<metamap>? [arity1] body)
              (^<metamap>? [arity2] body)
              ..
              (^<metamap>? [arityN] body)

  arity :=> <ret-typehint>? [<arg1-typehint>? <arg1>
                            ..
                            <argN-typehint>? <argN>]

  body :=> <metamap> <forms>

The declaration outline locates optional docstrings and metadata, single- and multiple-arity forms, type hints, and bodies. section 2.1.1

How Clojure: The Essential Reference covers it

How deep it goes
Works through macro expansion, declaration grammar, metadata, conditions, and type hints without claiming a complete formal grammar.
Examples
Uses a greeting, metadata-selected profiling, failing condition checks, and HMAC signing with reflection warnings.
What it assumes
Introduces informal grammar notation while building on familiarity with Clojure forms and function calls.
What you can do after
Practice/perform named function definitions with docstrings, arities, metadata, conditions, and type hints.
How it connects
Connects `defn` to `def`, `fn`, `defn-`, metadata, function conditions, and Java interop.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Clojure: The Essential Reference. The section links point to the parts of the book it draws on.