[Scheme] Quoting

Literal representation

Scheme allows you to write lists as literals using quoting. Just as you can write a literal boolean or number in your program, you can write a literal list if you use the special form quote.

Quote is a special form, not a procedure, because it doesn't evaluate its argument in the usual way. (Its argument is really just a literal representation of a data structure, which may look like a Scheme expression, but it isn't.) For example, the expression (quote (1 2 3)) returns a pointer to a list (1 2 3), i.e., a sequence of cdr linked pairs whose car values are (pointers to) to 1, 2, and 3.

You can use quote expressions as subexpressions of other expressions, because they just return pointer values like anything else. For example, the expression (define foo (quote (1 2 3))) defines (and binds) a variable foo, and initializes its binding with (a pointer to) a three-element list.

We can draw the resulting situation this way:

    +---+    +---+---+      +---+---+      +---+---+ 
foo | *-+--->| * | *-+----->| * | *-+----->| * | * | 
    +---+    +-+-+---+      +-+-+---+      +-+-+---+ 
               |              |              | 
              \|/            \|/            \|/ 
               1              2              3

quote takes exactly one argument, and returns a data structure whose printed representation is the same as what you typed in as the argument to quote. Scheme does not evaluate the argument to quote as an expression--it just gives you a pointer to a data structure.

Note that quote does not generally construct a character string--it constructs a data structure that may be a list or tree or even an array. It's a very general quoting facility, much more powerful than the double quotes around character strings, which only construct string objects.

Scheme provides a cleaner way of writing quoted expressions, using the special single-quote character '. Rather than writing out (quote some-expression), you can just precede the quoted expression with the single-quote character. For example, we can write the same definition of foo as (define foo '(1 2 3)). You don't need a closing quote, because of Scheme's parenthesized prefix syntax--it can figure out where the quoted data structure ends.

Constantness

One subtlety about quote is that a quote expression doesn't create a data structure every time it's called--evaluating the same expression many times may return many pointers to the same structure.

Consider the procedure definition:

(define (foo) 
  '(1 2 3))

The list (1 2 3) may be created when we define the procedure foo, and each time we call it, it may return a pointer to that same list. (Exactly what happens depends on the particular implementation of Scheme, but most work this way, for efficiency reasons. Evaluating the quote expression just fetches a pointer to a data structure that was created beforehand.)

For this reason, it's an error to modify a data structure returned from a quote form. Unfortunately, many Scheme systems don't detect this error, and will let you do it.

If you want a new data structure each time, you should use a procedure like list, which always creates a new data structure. (list, which we'll discuss more later, is a standard Scheme procedure that takes any number of arguments, and creates a list of those items.)

For example, if we want the procedure foo to return a new list (1 2 3) every time, we can write:

(define (foo) 
  (list 1 2 3))

Homoiconicity

Programs often need to refer to literal data values--data that you type directly into the program. In many languages, the only literals are fairly simple values like integers and strings. In Scheme, you can use simple literals or complicated ones that represent (pointers to) data structures like nested lists. Earlier, I showed how to create list literals using quoting.

You've probably noticed that the syntax of Scheme code and the textual representation of Scheme data are very similar. So, for example, (min 1 2) is a combination if it's viewed as code, but it's also the standard textual representation of a list containing the symbol min and the integers 1 and 2.

(A symbol is a data object that's sort of like a string, but with some special properties, which will be explained in the next chapter.)

The resemblance between code and data is no accident, and it can be very convenient, as later examples will show. It can be confusing, too, however, so it's important to know when you're looking at a piece of code and when you're looking at a piece of literal data.

The first thing to understand is quoting. In Scheme, the expression (min 1 2) is a procedure call to min with the arguments 1 and 2. As I explained earlier, we can quote it by wrapping it in the special form (quote ...), however, and get a literal list (min 1 2).

For example, the definition:

(define foo 
  (quote (min 1 2)))

defines and binds foo, initializing the binding with (a pointer to) the list (min 1 2).

Of course, as I explained earlier, we can use ' as a euphemism for (quote ... ). We can define very complicated literals this way, if we want to. Here's a procedure that returns a nested list of nested lists of integers and booleans and symbols:

(define (fubar) 
  '(((1 two #f) (#t 3 four)) 
    ((five #f 6) (seven 8 #t)) 
    ((#f 9 10)) ((11 12 #f))))

that's a pretty useless procedure, but it's very convenient to just be able to type in printed representations of nested data structures and have Scheme construct them automatically for you. In most languages you'd have to do some fairly tedious hacking to construct a list like that.

As we'll see in a later chapter, Scheme also supports quasiquotation, which lets you construct mostly-literal data structures, and create customized variations on them easily; quasiquotation will be discussed in a later chapter.


Reference

An Introduction to Scheme and its Implementation

你可能感兴趣的:([Scheme] Quoting)