怎么做的work?
quote
实施起来真的非常简单。它几乎什么也不做。这quote
特殊运算符只是按原样返回封闭的对象。而已。没有评价。对象不会以任何方式改变。
引用表格的评估
也许是阅读 1960 年麦卡锡著作的好时机:
符号表达式的递归函数及其机器计算,第一部分 http://www-formal.stanford.edu/jmc/recursive.pdf
第 16/17 页解释了评估eval
. Here:
eq [car [e]; QUOTE] → cadr [e];
或用 s 表达式表示法:
(cond
...
((eq (car e) 'quote)
(cadr e))
...)
上面的代码实现了评估规则QUOTE
:如果表达式是一个列表并且列表的第一个元素是符号QUOTE
,然后返回列表的第二个元素。
引用列表与创建列表的等价性LIST
(equal (quote (+ 1 (* 1 2)))
(list '+ 1 (list '* 1 2)))
结果是T
。这意味着两个结果列表在结构上是等效的。
(eq (quote (+ 1 (* 1 2)))
(list '+ 1 (list '* 1 2)))
结果是NIL
。这意味着链表的第一个 cons 单元不是相同的对象。EQ
测试我们是否真的有相同的 cons cell 对象。
所以主要的区别是QUOTE
是一个内置运算符,它返回文字和未计算的数据。然而LIST
是一个创建一个函数新的,新鲜的列表及其参数作为内容。
查看相关效果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))
quote 是一个函数吗?
quote
不能是函数,因为它返回未计算的封闭数据。因此,这是一个特殊的评估规则。
If quote
是一个函数,它的参数被评估。但这正是NOT what quote
应该做的。
为什么 Lisp 需要QUOTE
?
Lisp 通常使用 s 表达式来编写 Lisp 代码。因此,s 表达式具有表示数据和我们用它来编写程序的双重目的。在 Lisp 程序中,列表用于函数调用、宏形式和特殊形式。符号用作变量:
(+ n 42)
Here (+ n 42)
是一个列表并且n
是一个符号。但我们还想在程序中使用列表作为数据,并且希望使用符号作为数据。因此我们必须引用它们,这样 Lisp 就不会将它们视为程序,而是视为数据:
(append '(+ n) '(42)) evaluates to (+ n 42)
因此,在 Lisp 程序中,列表和变量默认是语言元素的一部分,例如函数调用和变量。如果我们想使用列表和符号作为文字数据,我们必须引用它们,以防止评估器将它们视为 Lisp 代码来评估。