Next: baselib syntax binding, Previous: baselib iteration, Up: baselib [Index]
“Backquote” or “quasiquote” expressions are useful for constructing a list or vector structure when some but not all of the desired structure is known in advance.
?qq-template should be as specified by the grammar at the end of this entry.
If no unquote
or unquote-splicing
forms appear within the
?qq-template, the result of evaluating (quasiquote
?qq-template)
is equivalent to the result of evaluating
(quote ?qq-template)
.
If an (unquote ?expression …)
form appears inside a
?qq-template, however, the ?expressions are evaluated
(“unquoted”) and their results are inserted into the structure instead
of the unquote
form.
If an (unquote-splicing ?expression …)
form appears
inside a ?qq-template, then the ?expressions must evaluate
to lists; the opening and closing parentheses of the lists are then
“stripped away” and the elements of the lists are inserted in place of
the unquote-splicing
form.
Any unquote-splicing
or multi–operand unquote
form must
appear only within a list or vector ?qq-template.
The following abbreviations may be used:
(quasiquote ?qq-template) = `?qq-template (unquote ?expression) = ,?expression (unquote-splicing ?expression) = ,@?expression
Examples:
`(list ,(+ 1 2) 4) ⇒ (list 3 4) (let ((name 'a)) `(list ,name ',name)) ⇒ (list a (quote a)) `(a ,(+ 1 2) ,@(map abs '(4 -5 6)) b) ⇒ (a 3 4 5 6 b) `((foo ,(- 10 3)) ,@(cdr '(c)) . ,(car '(cons))) ⇒ ((foo 7) . cons) `#(10 5 ,(sqrt 4) ,@(map sqrt '(16 9)) 8) ⇒ #(10 5 2 4 3 8) (let ((name 'foo)) `((unquote name name name))) ⇒ (foo foo foo) (let ((name '(foo))) `((unquote-splicing name name name))) ⇒ (foo foo foo) (let ((q '((append x y) (sqrt 9)))) ``(foo ,,@q)) ⇒ `(foo (unquote (append x y) (sqrt 9))) (let ((x '(2 3)) (y '(4 5))) `(foo (unquote (append x y) (sqrt 9)))) ⇒ (foo (2 3 4 5) 3)
Quasiquote forms may be nested. Substitutions are made only for
unquoted components appearing at the same nesting level as the outermost
quasiquote
. The nesting level increases by one inside each
successive quasiquotation, and decreases by one inside each unquotation.
`(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f) ⇒ (a `(b ,(+ 1 2) ,(foo 4 d) e) f) (let ((name1 'x) (name2 'y)) `(a `(b ,,name1 ,',name2 d) e)) ⇒ (a `(b ,x ,'y d) e)
A quasiquote
expression may return either fresh, mutable objects
or literal structure for any structure that is constructed at run time
during the evaluation of the expression. Portions that do not need to
be rebuilt are always literal. Thus:
(let ((a 3)) `((1 2) ,a ,4 ,'five 6))
may be equivalent to either of the following expressions:
'((1 2) 3 4 five 6) (let ((a 3)) (cons '(1 2) (cons a (cons 4 (cons 'five '(6))))))
However, it is not equivalent to this expression:
(let ((a 3)) (list (list 1 2) a 4 'five 6))
It is a syntax violation if any of the identifiers quasiquote
,
unquote
, or unquote-splicing
appear in positions within a
?qq-template other than as described above.
The following grammar for quasiquote expressions is not context–free. It is presented as a recipe for generating an infinite number of production rules. Imagine a copy of the following rules for N = 1, 2, 3, …; N keeps track of the nesting depth.
;;This is the argument of QUASIQUOTE. ;; ?qq-template -> ?qq-template-1 ;;This represents an expression to be evaluated. It exists ;;to represent ?qq-template-(N-1) when N=1. ;; ?qq-template-0 -> ?expression ?quasiquotation-N -> (quasiquote ?qq-template-N) ?qq-template-N -> ?lexeme-datum | ?list-qq-template-N | ?vector-qq-template-N | ?unquotation-N ?list-qq-template-N -> (?qq-template-or-splice-N*) | (?qq-template-or-splice-N+ . ?qq-template-N) | ?quasiquotation-(N+1) ?vector-qq-template-N -> #(?qq-template-or-splice-N*) ?unquotation-N -> (unquote ?qq-template-(N-1)) ?qq-template-or-splice-N -> ?qq-template-N | ?splicing-unquotation-N ?splicing-unquotation-N -> (unquote-splicing ?qq-template-(N-1)*) | (unquote ?qq-template-(N-1)*)
In quasiquotation
s, a ?list-qq-template-N can
sometimes be confused with either an ?unquotation-N or a
?splicing-unquotation-N. The interpretation as an
?unquotation-N or ?splicing-unquotation-N
takes precedence.
Next: baselib syntax binding, Previous: baselib iteration, Up: baselib [Index]