| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
[R5RS] Quasiquotation is a convenient way to build a structure that has some fixed parts and some variable parts. See the explanation below.
`template
[R5RS]
The syntax `x is read as (quasiquote x).
[R5RS] These syntaxes have meaning only when they appear in the template of quasiquoted form. The standard says nothing about these syntaxes appear outside of quasiquote. Gauche signals an error in such case, for it usually indicates you forget quasiquote somewhere. See the explanation below for the meaning of these.
,datum
,@datum
[R5RS]
The syntaxes ,x and ,@x are read as (unquote x)
and (unquote-splicing x), respectively.
Suppose you want to create a list (foo bar x y),
where foo and bar are symbols, and x and y
are the value determined at runtime. (For the sake of explanation,
let's assume we have variables x and y that provides those
values.) One way to do that is to call the function list
explicitly.
(let ((x 0) (y 1)) (list 'foo 'bar x y)) ⇒ (foo bar 0 1) |
You can do the same thing with quasiquote, like this:
(let ((x 0) (y 1)) `(foo bar ,x ,y)) ⇒ (foo bar 0 1) |
The difference between the two notations is that the explicit version quotes the parts that you want to insert literally into the result, while the quasiquote version unquotes the parts that you don't want to quote.
The quasiquote version gets simpler and more readable when you have lots of static parts with scattered variable parts in your structure.
That's why quasiquote is frequently used with
legacy macros, which are basically a procedure that
create program fragments from variable parts provided as
macro arguments. See the simple-minded my-if macro
that expands to cond form:
(define-macro (my-if test then else)
`(cond (,test ,then)
(else ,else)))
(macroexpand '(my-if (< n 0) n (- n)))
⇒ (cond ((< n 0) n) (else (- n)))
|
Note the two elses in the macro definition; one isn't unquoted,
thus appears liteally in the output, while another is unquoted and
the corresponding macro argument is inserted in its place.
Of course you can use quasiquotes unrelated to macros. It is a general way to construct structures. Some even prefer using quasiquote to explicit construction even most of the structure is variable, for quasiquoted form can be more concise. Gauche also tries to minimize runtime allocation for quasiquoted forms, so it may potentially be more efficient; see "How static are quasiquoted forms?" below.
When (unquote-splicing expr) appears in a quasiquoted form,
expr must evaluate to a list, which is spliced into the
surrounding context. It's easier to see examples:
(let ((x '(1 2 3))) `(a ,@x b)) ⇒ (a 1 2 3 b) (let ((x '(1 2 3))) `(a ,x b)) ⇒ (a (1 2 3) b) (let ((x '(1 2 3))) `#(a ,@x b)) ⇒ #(a 1 2 3 b) |
Compare the unquote version and unquote-splicing version. Splicing also works within a vector.
When quasiquoted form contains variable parts, what happens at
runtime is just the same as when an explicit form is used:
`(,x ,y) is evaluated exactly like (list x y).
However, Gauche tries to minimize runtime allocation when
a quasiquoted form has static parts.
First of all, if there's no variable parts in quasiquoted
form, like `(a b c), the entire form is allocated statically.
If there is a static tail in the sturcture, it is also allocated
statically; e.g. `((,x a b) (,y c d)) works like
(list (cons x '(a b)) (cons y '(c d))).
Furthermore, when an unquoted expression is a
constant expressoin, Gauche embeds it into the static
form. If you've defined a constant like
(define-constant x 3), then the form
`(,x ,(+ x 1)) is compiled as the constant '(3 4).
(See Definitions, for the explanation of define-constant form.)
In general it is hard to say which part of quasiquoted form is compiled as a static datum and which part is not, so you shouldn't write a code that assumes some parts of the structure returned from quasiquote are freshly allocated. In other words, you better avoid mutating such structures.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated by Shiro Kawai on October, 7 2008 using texi2html 1.78.