Next: , Previous: , Up: Derived expression types   [Index]


4.2.8 Quasiquotation

syntax: quasiquote ⟨qq template⟩
syntax: `⟨qq template⟩
auxiliary syntax: unquote
auxiliary syntax: ,
auxiliary syntax: unquote-splicing
auxiliary syntax: ,@

“Quasiquote” expressions are useful for constructing a list or vector structure when some but not all of the desired structure is known in advance. If no commas appear within the ⟨qq template⟩, the result of evaluating `⟨qq template⟩ is equivalent to the result of evaluating '⟨qq template⟩. If a comma appears within the ⟨qq template⟩, however, the expression following the comma is evaluated (“unquoted”) and its result is inserted into the structure instead of the comma and the expression. If a comma appears followed without intervening whitespace by a commercial at-sign (@), then it is an error if the following expression does not evaluate to a list; the opening and closing parentheses of the list are then “stripped away” and the elements of the list are inserted in place of the comma at-sign expression sequence. A comma at-sign normally appears only within a list or vector ⟨qq template⟩.

Note: In order to unquote an identifier beginning with , it is necessary to use either an explicit unquote or to put whitespace after the comma, to avoid colliding with the comma at-sign sequence.

`(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 ((foo '(foo bar)) (@baz 'baz))
  `(list ,@foo , @baz))
  ⇒ (list foo bar baz)

Quasiquote expressions can 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 newly allocated, 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 treated as 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))

The two notations `⟨qq template⟩ and (quasiquote ⟨qq template⟩) are identical in all respects. ,⟨expression⟩ is identical to (unquote ⟨expression⟩), and ,@⟨expression⟩ is identical to (unquote-splicing ⟨expression⟩). The write procedure may output either format.

(quasiquote (list (unquote (+ 1 2)) 4))
  ⇒ (list 3 4)

'(quasiquote (list (unquote (+ 1 2)) 4))
  ⇒ `(list ,(+ 1 2) 4)
  i.e., (quasiquote (list (unquote (+ 1 2)) 4))

It is an error if any of the identifiers quasiquote, unquote, or unquote-splicing appear in positions within a ⟨qq template⟩ otherwise than as described above.


Next: Case-lambda, Previous: Exception handling, Up: Derived expression types   [Index]