Cover by Brian Carper, Christophe Grand, Chas Emerick

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

O'Reilly logo

Debugging Macros

Macros can be notoriously difficult to debug. Clojure helpfully catches a variety of compile-time errors, but care must be taken to use the power that macros offer without being snared by their traps.

Consider what happens when referring to a var that isn’t yet defined. In a function, this will trigger a compile-time error:

(defn oops [arg] (frobnicate arg))
;= #<CompilerException java.lang.Exception:
;=   Unable to resolve symbol: frobnicate in this context (NO_SOURCE_FILE:1)>

Sadly, we can define a similar macro without any warning:

(defmacro oops [arg] `(frobnicate ~arg))
;= #'user/oops

Trying to use this macro will produce an error when it is used:

(oops 123)
;= #<CompilerException java.lang.IllegalStateException:
;=   Var user/frobnicate is unbound. (NO_SOURCE_FILE:0)>

What happened? Remember that macros execute at compile time. At compile time, Clojure doesn’t (and can’t) know if the symbol frobnicate will refer to a var that has a defined value at runtime or not. The macro sees and returns only lists, symbols, and other data structures. Whether those symbols are valid when the code produced by the macro is executed is not for the macro to decide. This can make debugging macros tricky, but we have a couple of tools at our disposal.

Macroexpansion

The most fundamental tool in debugging macros is macroexpand-1. This function takes a data structure (in debugging contexts, often a quoted macro form) and taps into the Clojure compiler to return the code—which, remember, is ...

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required