Go to the first, previous, next, last section, table of contents.

quasiquote

The special form quasiquote behaves a lot like quote, allowing 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 at runtime.

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 quote expression is compiled.(10) quasiquote constructs an s-expression at run time, when the 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 symbols foo and baz, but whose middle element is the value of the variable bar.

Try this in your scheme system:

Scheme>(define bar 2)
baz
Scheme>(quasiquote (foo (unquote bar) baz))
(foo 2 baz)

Without quasiquote and 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 form (list 'quote foo 'baz). For this simple example, that's probably at least as clear, because the use of (quasiquote ...) and (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 (quote ...) and a comma character (,) to replace (unquote ...).

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 quasiquote---it's 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 printf procedure 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 string "Sunday", printf("Welcome. It's %s.", day_of_week) prints "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 procedure calls, (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.

unquote-splicing

Scheme provides a variant of unquote for use when you want to merge an unquoted list into a literal list, rather than nesting it.

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 ,expr), we can use use (unquote-splicing expr), or the syntactically sugared form, ,@expr.

Scheme> `(And remember that ,@phrase of the day)
(And remember that the Lord helps those who take a big helping for
themselves)

Go to the first, previous, next, last section, table of contents.