liveBook · Manning

Macroexpand

As explained in Clojure: The Essential Reference

macroexpand is a Clojure function that expands a macro invocation into the form it produces before evaluation.

`macroexpand` lets you inspect what a Clojure macro produces without evaluating the result. It is especially useful at the REPL when a macro behaves unexpectedly. Pass it a valid Clojure form, usually quoted so the invocation is supplied as data. section 4.2

`macroexpand` repeatedly expands the outermost form until it is no longer a macro invocation, then returns that form. It does not descend into nested forms. Use `macroexpand-1` for a single outermost expansion step, or `clojure.walk/macroexpand-all` to expand inner forms too. section 4.2

Check a threading macro

`(macroexpand '(-> {:a 2} :a inc))` returns `(inc (:a {:a 2}))`. This reveals how `->` arranges the calls; it does not evaluate them to `3`. section 2.3.1

Inspect a function definition

`(macroexpand '(defn hello [person] (str "hello " person)))` produces a `def` containing a `clojure.core/fn` form. The result shows the definition that `defn` generates rather than calling `hello`. section 2.1.1

(macroexpand-1 '(when-first [a [1 2 3]] (println a)))                        ; #1
;; (clojure.core/when-let [xs__5218__auto__ (clojure.core/seq [1 2 3])]
;;   (clojure.core/let [a (clojure.core/first xs__5218__auto__)]
;;     (println a)))

(macroexpand '(when-first [a [1 2 3]] (println a)))                          ; #2
;; (let* [temp__4670__auto__ (clojure.core/seq [1 2 3])]
;;   (clojure.core/when temp__4670__auto__
;;     (clojure.core/let [xs__5218__auto__ temp__4670__auto__]
;;       (clojure.core/let [a (clojure.core/first xs__5218__auto__)]
;;         (println a)))))

(clojure.walk/macroexpand-all '(when-first [a [1 2 3]] (println a)))        ; #3
;; (let* [temp__4670__auto__ (clojure.core/seq [1 2 3])]
;;   (if temp__4670__auto__
;;     (do (let* [xs__5218__auto__ temp__4670__auto__]
;;           (let* [a (clojure.core/first xs__5218__auto__)]
;;              (println a))))))

Compare all three expansion functions on the same `when-first` invocation. The `macroexpand` result still contains an inner `when`; only `macroexpand-all` expands it. section 4.2

Use `macroexpand` when the outer expansion is enough to explain a macro. If a remaining nested macro matters, switch to `clojure.walk/macroexpand-all`. section 4.2

How Clojure: The Essential Reference covers it

How deep it goes
Defines the input and return behavior, contrasts three expansion depths, and stops `macroexpand` at nested forms.
Examples
Shows expansions of `when-first`, `defn`, and the `->` threading macro.
What it assumes
Assumes familiarity with Clojure expressions and macro invocations; demonstrates supplying a quoted form.
What you can do after
Diagnose/debug with it by inspecting a quoted macro invocation’s outer expansion before evaluation.
How it connects
Connects macro expansion to `macroexpand-1`, `clojure.walk/macroexpand-all`, quoting, and macro debugging.

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.