How to explain scheme expression '(a 'b)

2019-07-16 03:49发布

问题:

'(a 'b) gives out the answer (a 'b). How does this work when there is no binding for a (which is unquoted).

回答1:

This is what happens when we evaluate the expression:

'(a 'b)
=> (a 'b)

The ' quote is shorthand for the quote special form, see the linked documentation for more details:

(quote (a 'b))
=> (a 'b)

As you can see, it prevents the quoted arguments from being evaluated, so it doesn't matter if a is undefined, because a is not interpreted as a variable inside a quoted expression. It's a different thing if we tried to build a list like this:

(list a 'b)

The above will produce an error, because a is an undefined variable, whereas b is a quoted expression. This will work, though - because both elements in the list are quoted:

(list 'a 'b)
=> (a b)

And here's another way to build the list shown in the question:

(list 'a ''b)
=> (a 'b)


回答2:

The quote that prefixes the list expression prevents the evaluation of the components. If you were to write, say, (list a 'b), you'd end up with a problem if there was no binding.



回答3:

'something is syntactic sugar for (quote something).

So '(a 'b) is (quote (a (quote b))).

quote is not a function; it is a special form that converts the literal expression to the right into a runtime structure that looks like that expression.

  • Quoting a number or string literal will evaluate to the same as that literal: (quote 42) evaluates to 42
  • Quoting an identifier will produce a symbol: (quote apple) evaluates to the same as (string->symbol "apple")
  • Quoting a parenthesized form will produce a list, whose elements are the result of quoting each of the items in the parentheses: (quote (x 5 (a b))) evaluates as (list (quote x) (quote 5) (quote (a b)))

In (quote (a (quote b))), the second "quote" is not treated specially from any other identifier, because the right side of the first quote is taken literally, and none of it is evaluated as Scheme code.

So, (quote (a (quote b))) evaluates to the same as (list (string->symbol "a") (list (string->symbol "quote") (string->symbol "b"))). In other words, it's a list of 2 elements, the first of which is the symbol "a", and second of which is another list of 2 elements, the first of which is the symbol "quote", and the second of which is the symbol "b".

Then we have to get into how the Scheme REPL prints out values.

  • When the value is a list, it prints parentheses (( )), with recursively printed result of each of the list items inside.
  • When the value is a symbol, it prints the string of the symbol.
  • As a special exception, if it would otherwise print (quote something) (which would happen if it is printing a list of 2 elements, the first of which is the symbol "quote"), it will instead print 'something.

Therefore, the above list, which if not for the exception would be printed as (a (quote b)), will actually be printed as (a 'b).