What is the effect and use of ',
in backquoted expressions in lisp? Does it have a name and is it documented somewhere? And how common and useful is it?
For example:
(defmacro test-exp (exp)
`(format t "~&~S => ~S~%" ',exp ,exp))
My guess is that here it will take whatever exp
literally is, at macro expansion time, and replace ',exp
with it. (As opposed to evaluating exp
and replacing ,exp
with it).
You guessed right.
The special operator quote
defines an expression which evaluates to its subform, literally. For example:
(quote (looks like a function call))
The inner form looks like a function call, but for the Lisp reader, this is just a list of symbols. The expression (quote ...)
evaluates to that list, without trying to evaluate the list as code.
There is special syntax for quoting expression, the quote character, so that 'exp
is the same as (quote exp)
. That's usually how you write symbols when you don't want to evaluate them.
Quasiquotation is a way to quote only part of an expression.
The backtick acts like a quote: the data inside it is not evaluated, except when they are prefixed by a comma, in which case evaluation is toggle back on. The following expression
`(format t "~s" ,exp)
... could be written:
(list 'format 't '"~s" exp)
I added quotes before literals that otherwise would be self-evaluating, for completeness, but in practice you would write the same list as follows:
(list 'format t "~s" exp)
Here exp
is evaluated, and the whole form gives a list that ressembles a call to format
, where env
is replaced by whatever its value is.
The quote/comma combo you see in the example is a common idiom where you want to put an argument given at macroexpansion time (i.e. code) literally in the code being expanded, without evaluating it. If you test your macro by macroexpanding it, you can see the resulting code:
(macroexpand '(test-exp (+ 5 8)))
=> (FORMAT T "~&~S => ~S~%" '(+ 5 8) (+ 5 8))
The literal (+ 5 8)
form is placed within a (quote ...)
form, making it unevaluated at runtime. Meanwhile, the same expression is put as-is next to it, thus evaluating it at runtime. If you evaluate the resulting expression, it prints:
(+ 5 8) => 13