common-lisp Backquote - writing code templates for macros


Example

Macros return code. Since code in Lisp consists of lists, one can use the regular list manipulation functions to generate it.

;; A pointless macro
(defmacro echo (form)
  (list 'progn
        (list 'format t "Form: ~a~%" (list 'quote form))
        form))

This is often very hard to read, especially in longer macros. The Backquote reader macro allows one to write quoted templates that are filled in by selectively evaluating elements.

(defmacro echo (form)
  `(progn
     (format t "Form: ~a~%" ',form)
     ,form))

(macroexpand '(echo (+ 3 4)))
;=> (PROGN (FORMAT T "Form: ~a~%" '(+ 3 4)) (+ 3 4))

This version looks almost like regular code. The commas are used to evaluate FORM; everything else is returned as is. Notice that in ',form the single quote is outside the comma, so it will be returned.

One can also use ,@ to splice a list in the position.

(defmacro echo (&rest forms)
  `(progn
     ,@(loop for form in forms collect `(format t "Form: ~a~%" ,form))
     ,@forms))

(macroexpand '(echo (+ 3 4) 
                    (print "foo")
                    (random 10)))
;=> (PROGN
;    (FORMAT T "Form: ~a~%" (+ 3 4))
;    (FORMAT T "Form: ~a~%" (PRINT "foo"))
;    (FORMAT T "Form: ~a~%" (RANDOM 10))
;    (+ 3 4)
;    (PRINT "foo")
;    (RANDOM 10))

Backquote can be used outside macros too.