32

通过阅读有关 Lisp 的介绍性材料,我现在认为以下内容是相同的:

(list 1 2 3)

'(1 2 3)

但是,从我在 Clojure 和 Emacs Lisp 中使用带引号的形式时遇到的问题来看,它们并不相同。你能告诉我有什么区别吗?

4

4 回答 4

37

主要区别在于quote防止评估元素,而list 不会:

用户=> '(1 2 (+ 1 2))
(1 2 (+ 1 2))
用户=> (列表 1 2 (+ 1 2))
(1 2 3)

出于这个原因(以及其他原因),在描述文字集合时使用向量是惯用的 clojure:

用户=> [1 2 (+ 1 2)]
[1 2 3]
于 2010-10-09T19:38:52.203 回答
11

在 Common Lisp 中,带引号的对象是常量文字数据。您不应修改此数据,因为后果是不确定的。可能的后果是:修改共享数据,尝试修改只读数据,可能会发出错误信号,它可能正常工作,......

对于列表:

'(1 2 3)

上面是一个常量列表,它将由读者构造并对其自身进行评估,因为它被引用了。如果它出现在 Lisp 代码中,编译器会以某种方式将这些数据嵌入到 FASL 代码中。

(quote (1 2 3))是另一种写法。

(list 1 2 3)

这是对 Common Lisp 函数的调用,带有LIST三个参数和。评估结果是一个全新的列表。123(1 2 3)

相似的:

'(1 . 2)   and  (cons 1 2)

'#(1 2 3)  and  (vector 1 2 3)

一种是文字数据,另一种是构造这种数据结构的函数调用。

于 2010-10-09T17:04:15.073 回答
11

引用列表(例如'(1 2 3))应谨慎对待(通常为只读)。(请参阅 SO 回答何时在 Lisp 中使用 'quote何时在 Lisp 中使用 'quote)。

(list 1 2 3)将“cons”一个新的列表,独立于所有其他列表。

您可以在手册中nconc看到使用带引号的列表的陷阱示例。

而且,您可能知道,当您调用时'list- 显然会根据引用列表的内容对参数进行评估。并'quote采用单个参数,而不是'lists 可变数量的参数。

(list (+ 1 2) 3)     -->  (3 3)
(quote ((+ 1 2) 3))  -->  ((+ 1 2) 3)
于 2010-10-09T08:23:53.773 回答
0

它们的关系可以类似于使用“函数名称”和 的函数调用funcall

当您不知道在运行时会获得什么功能时,您可以使用funcall.

当您不知道在运行时可能会获得什么元素时,您可以使用list.


对于像我这样因为存在而感到困惑backquote并默认将其视为报价的人。

backquote不是quote

这是一个阅读器宏,可以扩展为quotelist或其他:

(macroexpand ''(1 2));=> '(1 2)
(macroexpand '`(1 2));=> '(1 2)
(macroexpand '`(1 ,2));=> (list 1 2)
(macroexpand '`(1 ,@foo));=> (cons 1 foo)
(macroexpand '`(1 ,@foo 2));=> (cons 1 (append foo '(2)))
于 2021-01-22T12:08:59.377 回答