在Lisp(Clojure,Emacs Lisp)中,列表和引用之间有什么区别?

时间:2010-10-09 08:07:24

标签: list clojure lisp elisp quote

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

(list 1 2 3)

'(1 2 3)

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

4 个答案:

答案 0 :(得分:35)

主要区别在于quote会阻止评估元素,而list 没有:

user=> '(1 2 (+ 1 2))
(1 2 (+ 1 2))
user=> (list 1 2 (+ 1 2))
(1 2 3)

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

user=> [1 2 (+ 1 2)]
[1 2 3]

答案 1 :(得分:9)

应谨慎对待引用列表(例如'(1 2 3))(通常为只读)。 (参见SO答案When to use 'quote in LispWhen to use 'quote in Lisp)。

(list 1 2 3)将“收集”一份新的清单,独立于所有其他清单。

您可以在manual for nconc中看到使用引用列表的陷阱示例。

而且,正如您可能知道的那样,当您调用'list时,显然会根据引用列表的内容来评估参数。并且'quote只接受一个参数,而'list的变量数量为(list (+ 1 2) 3) --> (3 3) (quote ((+ 1 2) 3)) --> ((+ 1 2) 3)

{{1}}

答案 2 :(得分:8)

在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)

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

答案 3 :(得分: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)))