liveBook · Manning

Macro hygiene

As explained in Clojure: The Essential Reference

Macro hygiene is the practice of preventing names introduced by macro expansion from unintentionally colliding with names in the surrounding code.

A macro produces code that runs in its caller’s context. Macro hygiene helps prevent names introduced by that code from accidentally colliding with names around the macro call. Clojure’s syntax-quote provides two practical safeguards: namespace qualification and automatically generated symbols. section 4.1

Inside syntax-quote:

  • An ordinary symbol is qualified, so `foo` becomes a symbol such as `user/foo` rather than an unqualified name. section 4.1
  • A symbol ending in `#` receives a generated identifier. Use the same spelling for references to a binding introduced within one syntax-quoted expression. section 4.1
  • `~'foo` deliberately inserts an unqualified `foo`. This bypasses the safeguards and is rarely appropriate. section 4.1

Give a macro’s local binding its own name

`(let [x# 1] x#)` produces a `let` whose binding and reference share a generated name, such as `x__37__auto__`. A retry macro similarly uses names such as `attempt#` and `warn#` for variables it introduces. section 4.1

`[foo foo# ~'foo]
;; [user/foo foo__45__auto__ foo]

Compare the three results in one expression: a qualified ordinary symbol, a generated symbol, and an intentionally unqualified symbol. section 4.1

Prefer qualification and `#`-suffixed names when constructing macro output. Use `macroexpand` to inspect the resulting code without executing it. section 4.1 section 4.0

How Clojure: The Essential Reference covers it

How deep it goes
Explains syntax-quote qualification, auto-gensym, and an escape hatch through expanded examples, but does not implement a purely hygienic macro system.
Examples
Compares `foo`, `foo#`, and `~'foo`, then shows a generated `let` binding and generated names in a retry macro.
What it assumes
Introduces gensym alongside defmacro, quote, and macroexpand rather than assuming prior knowledge of macro-inspection tools.
What you can do after
Apply it via Clojure syntax-quote and auto-gensym when introducing names in macros, and inspect expansions with `macroexpand`.
How it connects
Connects macro hygiene to syntax-quote, gensym, namespace qualification, unquote, and macro expansion.

Also explained in

Compare how 2 books explain macro hygiene →

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.