In the following when
macro:
(defmacro when (condition &rest body)
`(if ,condition (progn ,@body)))
Why is there an "at" @
sign?
In the following when
macro:
(defmacro when (condition &rest body)
`(if ,condition (progn ,@body)))
Why is there an "at" @
sign?
That macro definition is equivalent to
(defmacro when (condition &rest body)
(list 'if condition (cons 'progn body)))
but without the @
it would be equivalent to
(defmacro when (condition &rest body)
(list 'if condition (list 'progn body)))
Since body
is a list, that would cause it to be evaluated as if a parenthesized function call, e.g. (when t 1 2 3)
would get expanded as
(if t (progn (1 2 3)))
instead of the correct
(if t (progn 1 2 3))
The @
can also be thought of deconstructing the list and appending it to the list appears in as described in Practical Common Lisp.
`(a ,@(list 1 2) c)
is the equivalent of:
(append (list 'a) (list 1 2) (list 'c))
which produces:
(a 1 2 c)
When inserting computed values in quasiquoted section there are two operators:
,
,@
Comma
,
inserts the value of following expression in the quasi-quoted sexpr, comma-splice instead requires the expression following is a list and can be used only inside a quasi-quoted list: the effect is inserting all elements of the expression in the quasi-quoted list in the position where the operator appears.It's very easy to see the difference by making a little experiment
As you can see the use of
,@
will place the elements of the list directly inside in the expansion. Without you get instead the list placed in the expansion.Using
,@
with an expression that doesn't result in a list will be an error when the substitution is performed:Using
,@
not inside a list is instead an error when the quasi-quoted section is analyzed: