liveBook · Manning

Defmacro

As explained in Clojure: The Essential Reference

defmacro is a Clojure special form or macro-definition facility that defines a macro and binds it to a var in the current namespace.

`defmacro` defines a macro and binds it to a var in the current namespace. Use it when ordinary functions cannot express the desired behavior because arguments must be handled before evaluation, or when repeated code is better expressed as a new form. A macro receives forms as data during compilation and returns a Clojure expression for later evaluation. section 4.0 section 4.1

Its shape is `(defmacro name & fdecl)`, much like `defn`:

  • `name` must be a valid Clojure symbol; `fdecl` supplies arguments and a body. Multiple arities, destructuring, and `:pre` and `:post` conditions are supported. section 4.1
  • The macro body can access two implicit arguments: `&form`, the original call form, and `&env`, the local compilation environment. They reduce the limit on fixed arguments from 20 to 18. section 4.1
  • Defining a macro returns the `clojure.lang.Var` that refers to it. section 4.1

Build and inspect a conditional form

`(defmacro when [test & body] (list 'if test (cons 'do body)))` builds an `if` expression rather than evaluating `test` or `body` while expanding. `(macroexpand-1 '(when (= 1 2) (println "foo")))` produces `(if (= 1 2) (do (println "foo")))`. Evaluating the original `when` call prints nothing and returns `nil`. `macroexpand-1` shows the first expansion without expanding it further. section 4.1

(macroexpand '(defmacro simple [a] (str a))) ; #1

;; (do
;;   (clojure.core/defn simple ([&form &env a] (str a))) ; #2
;;   (. (var simple) (setMacro)) ; #3
;;   (var simple)) ; #4

Expanding a `defmacro` definition reveals a function definition with implicit `&form` and `&env` parameters, followed by marking its var as a macro and returning that var. section 4.1

Reach for `macroexpand` when generated code is surprising; it prints an expansion for inspection without executing it. For generated symbols or quoted code, `gensym` and quoting facilities are related tools. The essential contract remains simple: accept unevaluated forms, produce an expression. section 4.0 section 4.9

How Clojure: The Essential Reference covers it

How deep it goes
Specifies declaration syntax, implicit arguments, return value, and arity limit; illustrates expansion while deferring full declaration options to `defn`.
Examples
Uses a `when` definition and its first-level expansion, plus a retry-context macro and examples accessing `&form` and `&env`.
What it assumes
Assumes familiarity with `defn`-style declarations and Clojure forms while explaining the macro-specific compilation behavior.
What you can do after
Build it from scratch as a Clojure macro and inspect its generated expression with `macroexpand-1`.
How it connects
Connects macro definitions to `defn`, `macroexpand`, quoting, `gensym`, destructuring, and syntax-quote.

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.