Reading — step 1 of 5
Learn
You've seen basic macros. The deeper power: code that writes code.
Hygiene with gensym — generate unique symbols to avoid name capture:
(defmacro swap (a b)
(let ((tmp (gensym "TMP")))
`(let ((,tmp ,a))
(setf ,a ,b)
(setf ,b ,tmp))))
(let ((x 1) (y 2))
(swap x y)
(format t "~a ~a~%" x y))
Without gensym, if the user happened to bind tmp in their code, the macro would shadow it.
Recursive expansion:
(defmacro repeat (n &body body)
`(dotimes (i ,n) ,@body))
(defmacro repeat-with-index (n &body body)
`(dotimes (i ,n)
(let ((index i))
,@body)))
The second one binds index for the body — convention for what i represents.
Compile-time computation:
(defmacro precompute-table (size)
(let ((table (make-array size)))
(dotimes (i size)
(setf (aref table i) (* i i)))
`(quote ,table)))
(defparameter *squares* (precompute-table 100))
The table is built when the macro expands, baked into the program. No runtime computation.
Macros that build OTHER macros:
(defmacro define-status-checker (name status)
`(defmacro ,name (obj)
`(eq (slot-value ,obj 'state) ',,status)))
(define-status-checker active? :active)
(define-status-checker pending? :pending)
Anaphoric macros — capture a name implicitly:
(defmacro aif (test then &optional else)
`(let ((it ,test))
(if it ,then ,else)))
(aif (find-user id)
(format t "got ~a" it) ;; "it" is bound to the result
(format t "not found"))
The it variable is intentionally captured ("anaphoric" = referring back). Useful but trips up readers — Common Lisp purists usually prefer explicit variables.
Macros vs functions: macros run at compile time, functions at runtime. Use a function whenever possible — macros are harder to debug, can't be passed as values, and compose worse.
Useful macros to know:
loop— the iteration mini-languagewith-open-file,with-output-to-string— resource managementdefstruct,defclass— class definitions ARE macrossetf— universal mutator (knows how to write to any "place")
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…