100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace

Clojure Macros Cheat Sheet

Clojure Macros Cheat Sheet

Covers defmacro, quote/unquote/splice, gensym for hygiene, macroexpand for debugging, and common macro-writing patterns.

2 PagesAdvancedFeb 5, 2026

Defining a Basic Macro

Macros receive unevaluated code (forms) and must return code to be evaluated.

clojure
(defmacro unless [test then else]  `(if (not ~test) ~then ~else))(unless false  (println "runs")  (println "does not run"));; expands to:;; (if (not false) (println "runs") (println "does not run"))

Quote, Unquote & Splice

`` ` `` (syntax-quote), `~` (unquote), and `~@` (unquote-splice) are the core tools for building code templates.

clojure
(def x 10)'(1 2 x)     ;; => (1 2 x)          — quote: no evaluation`(1 2 ~x)    ;; => (1 2 10)         — syntax-quote + unquote evaluates x`(1 2 ~@[3 4 5]) ;; => (1 2 3 4 5)  — splices a sequence into the list(defmacro my-and  ([] true)  ([x] x)  ([x & rest] `(if ~x (my-and ~@rest) ~x)))

Hygiene with `gensym`/`#`

Avoid variable capture by generating unique symbol names inside syntax-quote.

clojure
;; Auto-gensym: any symbol ending in # inside `...` gets a unique suffix(defmacro my-or [a b]  `(let [val# ~a]     (if val# val# ~b)))(my-or false 42) ;; => 42, and `val#` can't collide with a caller's `val`;; Manual gensym for more control(defmacro my-swap! [a b]  (let [tmp (gensym "tmp")]    `(let [~tmp ~a]       (reset! ~a ~b)       (reset! ~b ~tmp))))

Debugging with `macroexpand`

Always inspect what your macro actually generates before trusting it.

clojure
(macroexpand-1 '(unless false (println "a") (println "b")));; => (if (clojure.core/not false) (println "a") (println "b"))(macroexpand '(my-or false 42));; fully expands nested macros too, useful for threading/-> style macros;; clojure.walk/macroexpand-all expands everything recursively(require '[clojure.walk :as walk])(walk/macroexpand-all '(my-or false (my-or nil 1)))

Macro-Writing Toolkit

The core forms/functions you'll reach for.

  • defmacro- defines a macro; body returns a form (code), not a value
  • ` (syntax-quote)- quotes a form while fully-qualifying symbols and enabling ~/~@
  • ~ (unquote)- evaluates an expression inside a syntax-quoted form
  • ~@ (unquote-splice)- splices a sequence's elements into the surrounding form
  • gensym / symbol#- produces a unique symbol to avoid variable capture (hygiene)
  • macroexpand-1 / macroexpand- shows the expansion, essential for debugging macros
  • &form / &env- implicit args available in defmacro bodies for advanced metaprogramming
Pro Tip

Write the macro's desired expansion as plain code first, get it working, then wrap it in `defmacro` and syntax-quote it — trying to write macro-generating logic and the target logic simultaneously is the most common source of Clojure macro bugs.

Was this cheat sheet helpful?

Explore Topics

#ClojureMacros#ClojureMacrosCheatSheet#Programming#Advanced#DefiningABasicMacro#QuoteUnquoteSplice#HygieneWithGensym#DebuggingWithMacroexpand#CheatSheet#SkillVeris
Advertisement
Sri Hayavadhana Info-Tech

Professional Web Designing Services

  • Responsive Websites
  • E-commerce Solutions
  • SEO Friendly Design
  • Fast & Secure
  • Support & Maintenance
Get a Free Quote

Share this Cheat Sheet