通过阅读关于Lisp的介绍材料,我现在认为以下内容是相同的:
(list 1 2 3)
'(1 2 3)
然而,从我在Clojure和Emacs Lisp中使用引用形式时遇到的问题来看,它们不相同。你能告诉我有什么区别吗?
答案 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 Lisp和When 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
的调用,有三个参数1
,2
和3
。评估结果时,结果是一个全新的列表(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
这是一个扩展为 quote
、list
或其他的读取器宏:
(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)))