Lisp引用内部工作

时间:2015-10-03 20:22:30

标签: lisp common-lisp quote

lisp quote如何在内部工作? 例如:

(quote (+ 1 (* 1 2)) )

似乎等同于

(list '+ 1 (list '* 1 2))

这意味着它是一种递归地象征Head值的方法。这个功能是内置的吗?

如果你不相信我,请运行(equal (quote (+ 1 (* 1 2))) (list '+ 1 (list '* 1 2)))

2 个答案:

答案 0 :(得分:3)

如何运作

quote实现起来非常简单。它什么都没做。 quote特殊运算符只是返回包含的对象。而已。没有评价。对象不会以任何方式改变。

引用表格的评估

可能是从1960年开始阅读麦卡锡的好时机:

Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I

第16/17页用eval解释评估。这里:

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。这意味着链表的第一个缺点单元不是相同的对象。 EQ测试我们是否真的拥有相同的cons单元对象。

  • QUOTE返回一个文字数据对象。修改此对象的后果未定义。所以,不要这样做。

  • LIST每次调用时都会返回一个新的consed列表。新的新列表不会与任何先前分配的列表共享任何利益单元格。

所以主要区别在于QUOTE是一个内置运算符,它返回文字和未评估的数据。而LIST是一个函数,它创建一个新的,新的列表,其参数为内容。

查看有关EQEQUAL的效果:

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是一个函数,那么它的参数就会被评估。但这正是 NOT quote应该做的事情。

为什么Lisp需要QUOTE

Lisp通常使用s表达式来编写Lisp代码。所以s表达式既有表示数据的目的,也有用它来编写程序。在Lisp程序中,列表用于函数调用,宏表单和特殊表单。符号用作变量:

(+ n 42)

此处(+ n 42)是一个列表,n是一个符号。但我们也希望在我们的程序中使用列表作为数据,并且我们希望使用符号作为数据。因此我们必须引用它们,以便Lisp不会将它们视为程序,而是作为数据:

(append '(+ n) '(42))  evaluates to (+ n 42)

因此,在Lisp程序中,列表和变量默认是语言元素的一部分,例如函数调用和变量。如果我们想使用列表和符号作为文字数据,我们必须引用它们,以防止评估者将它们视为要评估的Lisp代码。

答案 1 :(得分:2)

quote只会使其论点无法评估。但是什么是无价值的论点?

当定义Lisp程序时,它可以从文本源读取为s表达式,也可以直接用s表达式构造。宏将是生成s表达式的示例。无论哪种方式,都有一个数据结构,包括(大部分)代表程序的符号和conses。

大多数Lisp表达式将调用评估和编译机制来将此数据结构解释为程序中的术语。 quote被特别处理,传递这些未解释的符号并将其作为参数。简而言之,quote几乎没有任何作用 - 它返回的值已经存在并且只是通过。

您可以使用eq来测试传递和新构造之间的区别,以测试引用的返回值的标识:

(defun f () '(1 2))

(defun g () (list 1 2))

(eq (f) (f)) => T
(eq (g) (g)) => NIL

如您所见,quote每次都会返回相同的词。