How does lisp quote
work internally?
For example:
(quote (+ 1 (* 1 2)) )
seems to be equivalent to
(list \'+ 1 (li
How does it work?
quote
is really really simple to implement. It does mostly nothing. The quote
special operator just returns the enclosed object like it is. Nothing more. No evaluation. The object is not changed in any way.
Evaluation of quoted forms
Probably a good time to read McCarthy, from 1960:
Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I
Pages 16/17 explain evaluation with eval
. Here:
eq [car [e]; QUOTE] → cadr [e];
or in s-expression notation:
(cond
...
((eq (car e) 'quote)
(cadr e))
...)
Above code implements the evaluation rule for QUOTE
: If the expression is a list and the first element of the list is the symbol QUOTE
, then return the second element of the list.
Equivalence of a quoted list with a list created by LIST
(equal (quote (+ 1 (* 1 2)))
(list '+ 1 (list '* 1 2)))
The result is T
. This means that both result lists are structurally equivalent.
(eq (quote (+ 1 (* 1 2)))
(list '+ 1 (list '* 1 2)))
The result is NIL
. This means that the first cons cell of the linked lists are not the same objects. EQ
tests whether we really have the same cons cell object.
QUOTE
returns a literal data object. The consequences of modifying this object is undefined. So, don't do it.
LIST
returns a new freshly consed list each time it is called. The fresh new list will not share any cons cells with any earlier allocated list.
So the main difference is that QUOTE
is a built-in operator, which returns literal and unevaluated data. Whereas LIST
is a function which creates a new,fresh list with its arguments as contents.
See the effects with respect to EQ
and EQUAL
:
CL-USER 6 >
(flet ((foo () (quote (+ 1 (* 1 2))))
(bar () (list '+ 1 (list '* 1 2))))
(list (list :eq-foo-foo (eq (foo) (foo)))
(list :eq-foo-bar (eq (foo) (bar)))
(list :eq-bar-bar (eq (foo) (bar)))
(list :equal-foo-foo (equal (foo) (foo)))
(list :equal-foo-bar (equal (foo) (bar)))
(list :equal-bar-bar (equal (foo) (bar)))))
((:EQ-FOO-FOO T)
(:EQ-FOO-BAR NIL)
(:EQ-BAR-BAR NIL)
(:EQUAL-FOO-FOO T)
(:EQUAL-FOO-BAR T)
(:EQUAL-BAR-BAR T))
is quote a function?
quote
can't be a function, since it returns its enclosed data unevaluated. Thus it is a special evaluation rule.
If quote
were a function, it's arguments were evaluated. But that's exactly what is NOT what quote
is supposed to do.
why does Lisp need QUOTE
?
Lisp usually uses s-expressions to write Lisp code. So s-expressions have a both purpose to denote data and we use it to write programs. In a Lisp program lists are used for function calls, macro forms and special forms. symbols are used as variables:
(+ n 42)
Here (+ n 42)
is a list and n
is a symbol. But we also want to use lists as data in our programs and we want to use symbols as data. Thus we have to quote them, so that Lisp will not see them as programs, but as data:
(append '(+ n) '(42)) evaluates to (+ n 42)
Thus in a Lisp program, lists and variables are by default part of the language elements, for example as function calls and variables. If we want to use lists and symbols as literal data, we have to quote them, to prevent the evaluator treating them as Lisp code to evaluate.