The special form
quasiquote behaves a lot like
you to write out literal expressions in your program, using the standard
textual representation of s-expressions. Scheme automatically constructs
the data structures.
quasiquote is much more powerful than
quote, however, because you can write expressions that are
mostly literal, but leave holes to be filled in with values computed
For example, the value of the expression
(quote (foo bar baz))
is a list
(foo bar baz). Likewise, the value of the expression
(quasiquote (foo bar baz)) is a list
(foo bar baz).
There's a big difference, though.
quote constructs an s-expression at
compile time, when the procedure containing the
quasiquote constructs an s-expression at run time,
quasiquote form is executed. This allows Scheme
to "customize" a data structure, so that you actually get a
different data structure each time you execute the same
quasiquote form. You can use the
unquote operator to
specify which parts should be customized.
For example, suppose you want to write a procedure that creates a
three-element list whose first and last elements are the literal
baz, but whose middle element is the
value of the variable
Try this in your scheme system:
Scheme>(define bar 2) baz Scheme>(quasiquote (foo (unquote bar) baz)) (foo 2 baz)
unquote, you could get the same
effect by replacing
(quasiquote (foo (unquote bar) baz)) with
(list (quote foo) bar (quote baz)), or the equivalent sugared
(list 'quote foo 'baz). For this simple example,
that's probably at least as clear, because the use of
(unquote ...) is rather clunky.
To make it easier to write quasiquoted expressions, Scheme provides a little
syntactic sugar. Just as you can use a single quote character and write
'(foo bar baz) instead of
(quote (foo bar baz), you can
use a backquote character (
`) to replace
and a comma character (
,) to replace
Now we can do this:
Scheme>`(foo ,bar baz) (foo 2 baz)
This is much clearer. Intuitively, the backquote character means "construct an s-expresson of the following (literal) form, except where commas appear," and the comma character means "use the value of the following expression here, instead of using it literally."
Now you can see why it's called
a way of writing "mostly quoted" expressions, instead of pure literals.
You can turn quoting off where you want to. This is particularly useful
in constructing s-expressions that are in fact mostly literal,
especially if they're complicated.
For a simple example, suppose you want to write a procedure that constructs a greeting to print to a user. The greeting is always mostly the same, but includes the current day of the week:
Scheme> (define day-of-week 'Sunday) day-of-week Scheme> (define (make-greeting) `(Welcome to the FooBar system! We hope you enjoy your visit on this fine ,day-of-week))) greet
Scheme>(make-greeting) (Welcome to the FooBar system! We hope you enjoy your visit on this fine Sunday) Scheme>(set! day-of-week 'Monday) day-of-week Scheme>(make-greeting) (Welcome to the FooBar system! We hope you enjoy your visit on this fine Monday)
You may have notice that this is somewhat similar to formatted output
in other languages you've used, like C. (C's
takes a string that is (mostly) quoted, but has special escape characters
in it to tell where to substitute the printed representation of runtime
values. For example, if
day_of_week holds a pointer to the
printf("Welcome. It's %s.", day_of_week)
Welcome. It's Sunday.")
The nice thing about Scheme quasiquotation is that it works on normal data structures. For example, suppose you want to write a routine that creates an association list with several literal elements, and a several customized ones.
(define (create-shipping-employee-association name) `((name ,name) (employee-id-no ,(get-next-employee-id!)) (department shipping) (hire-date ,(get-day) ,(get-month) ,(get-year))))
(Notice that here that most of the unquoted expressions are calls to procedures, whose return values will be used. We can fill the holes in our templates with anything we want, not just variable values.)
Depending on the value of the variable the values returned by the
(new-shipping-employee-alist "Philboyd Studge")
will return something like
((name "Philboyd Studge") (employee-id-no 6357) (department shipping) (hire-date 18 August 1997))
Here it should be clear that
quasiquote has let us write out a
stereotyped data structure, and
unquote lets us fill in the varying
parts. More complicated examples would be make this benefit clearer,
but I'll leave them to your imagination.
Scheme provides a variant of
unquote for use when you want
to merge an unquoted list into a literal list, rather than nesting
For example, suppose you want to embed a phrase in a sentence, where the phrase is a list of symbols, and the sentence is a list of symbols.
If you tried this with unquote, you'd get a nested list, rather than just a list of symbols:
Scheme> (define phrase-of-the-day '(the Lord helps those who take a big helping for themselves)) phrase-of-the-day Scheme> `(Remember that ,phrase-of-the-day) (Remember that (the Lord helps those who take a big helping for themselves))
Rather than using
), we can use use
or the syntactically sugared form,
Scheme> `(And remember that ,@phrase of the day) (And remember that the Lord helps those who take a big helping for themselves)