(import (rnrs)) ;R6RS (import (rnrs base)) ;R6RS (import (scheme r5rs)) ;R7RS (import (scheme base)) ;R7RS
`template (quasiquote template) , unquote ,@ unquote-splicing
The backtick character is used to start a quasiquote expression. Comma is used before expressions that should be inserted in the structure. Comma at-sign is similar, but the result of the expression is a list that is spliced into the structure.
`(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)
The reader recognizes the abbreviations. Similarly, writer implementations often recognize opportunities to use these abbreviations, though they are not required to do so.
Here is a way to see the abbreviation: (car '`()) => quasiquote.
If an (unquote expression ...) form appears inside a template, the expressions are evaluated and their results are inserted into the structure instead of the unquote form.
If an (unquote-splicing expression ...) form appears inside a 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.
(let ((name 'foo))
`((unquote name name name)))
=> (foo foo foo)
(let ((name '(foo)))
`((unquote-splicing name name name)))
=> (foo foo foo)
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))
If no unquote or unquote-splicing forms appear within the template, the result of evaluating (quasiquote template) is equivalent to the result of evaluating (quote template).
\[la]template\[ra] ->
\[la]template 1\[ra]
\[la]template 0\[ra] ->
\[la]expression\[ra]
\[la]quasiquotation D\[ra] ->
(quasiquote \[la]template D\[ra])
\[la]template D\[ra] ->
\[la]lexeme datum\[ra]
| \[la]list template D\[ra]
| \[la]vector template D\[ra]
| \[la]unquotation D\[ra]
\[la]list template D\[ra] ->
(\[la]template or splice D\[ra]*)
| (\[la]template or splice D\[ra]+ . \[la]template D\[ra])
| \[la]quasiquotation D+1\[ra]
\[la]vector template D\[ra] ->
#(\[la]template or splice D\[ra]*)
\[la]unquotation D\[ra] ->
(unquote \[la]template D-1\[ra])
\[la]template or splice D\[ra] ->
\[la]template D\[ra]
| \[la]splicing unquotation D\[ra]
\[la]splicing unquotation D\[ra] ->
(unquote-splicing \[la]template D-1\[ra]*)
| (unquote \[la]template D-1\[ra]*)
In \[la]quasiquotation\[ra]s, a \[la]list template D\[ra] can sometimes be confused with either an \[la]unquotation D\[ra] or a \[la]splicing unquotation D\[ra]. The interpretation as an \[la]unquotation\[ra] or \[la]splicing unquotation D\[ra] takes precedence.
Note that R6RS extends quasiquote to support any number of expressions inside the unquoting forms. To get the R5RS/R7RS grammar: remove the * in the unquote-splicing form; remove the unquote form in the last rule; and add the rule '\[la]template D\[ra] to \[la]list template D\[ra].
`(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 ,(- 4) ,@(map - '(16 9)) 8)
=> #(10 5 -4 -16 -9 8)
(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) (- 9))))
=> (foo (2 3 4 5) -9)
https://github.com/gwatt/dollar-sign.
https://github.com/schemedoc/manpages/.