Skip to content
Macros
step 1/5

Reading — step 1 of 5

Read

~1 min readAdvanced Topics

Macros

The killer Lisp feature. Macros are functions that operate on CODE (s-expressions) BEFORE evaluation.

(defmacro unless (cond body)
    (list 'if cond '() body))

(unless (< x 0) (print "x is non-negative"))
;; expands to
(if (< x 0) () (print "x is non-negative"))

The macro receives cond = (< x 0) and body = (print "x is non-negative") as DATA. It RETURNS new code that gets evaluated.

This is FAR more powerful than functions because:

  • You can introduce new control flow (unless, when, cond, custom DSLs)
  • You can rewrite code (optimize, instrument, debug)
  • You can build language extensions (object systems, lazy evaluation, etc.)

In Scheme, the cleaner version uses hygienic macros (syntax-rules):

(define-syntax unless
    (syntax-rules ()
        ((_ cond body ...) (if cond (begin) (begin body ...)))))

Hygienic = automatic alpha-renaming so macro-introduced variables don't clash with user variables. Scheme requires this; Common Lisp uses gensym manually.

Macros are the main reason Lisp programmers stay loyal. No other language gives you syntax extension this powerful (Rust's macro_rules! and Racket's syntax-parse are inspired by Lisp).

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…