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

发布于 2024-09-26 22:15:54 字数 167 浏览 5 评论 0原文

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

(list 1 2 3)

'(1 2 3)

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

From reading introductory material on Lisp, I now consider the following to be identical:

(list 1 2 3)

'(1 2 3)

However, judging from problems I face when using the quoted form in both Clojure and Emacs Lisp, they are not the same. Can you tell me what the difference is?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

是伱的 2024-10-03 22:15:54

主要区别在于 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]

The primary difference is that quote prevents evaluation of the elements, whereas list
does not:

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

For this reason (among others), it is idiomatic clojure to use a vector when describing a literal collection:

user=> [1 2 (+ 1 2)]
[1 2 3]
倾城月光淡如水﹏ 2024-10-03 22:15:54

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

文字列表:

'(1 2 3)

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

(quote (1 2 3)) 是另一种编写方式。

(list 1 2 3)

这是对 Common Lisp 函数 LIST 的调用,带有三个参数 123。每个参数都会被评估。因为它们是数字,所以它们对自己进行评估。评估时,结果是一个全新的列表 (1 2 3)

编译代码中的数据共享

想象一下在 Lisp 文件中存在以下四个定义:

(defparameter *list1* (list 1 2 3))
(defparameter *list2* (list 1 2 3))
(defparameter *list3* '(1 2 3))
(defparameter *list4* '(1 2 3))

然后我们编译并加载该文件。

! (eq *list3* *list4*) 现在可能计算为 TNIL,具体取决于实现和编译器设置 !

原因:在 Common Lisp 中,如果文字列表 (!) 相似,Lisp 编译器可能会共享它们的结构。编译器检测到此处的列表相似,因此将仅分配一个列表。变量 *list1**list2* 都将指向这个列表。

上述两个列表的所有其他 EQ(对象相等)比较都将返回 NIL

其他一些数据结构的表示法:

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

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

'#S(FOO :a 1 :b 2)  and (make-foo :a 1 :b 2)   ; structure

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

In Common Lisp, quoted objects are constant literal data. The data is not evaluated. You should not modify this data, as the consequences are undefined. Possible consequences are: modification of shared data, attempt to modify read-only data, an error might be signalled, it might just work, shared data, ...

Literal lists:

'(1 2 3)

Above is a constant list, which will be constructed by the reader and evaluating to itself, because it is quoted. If it appears in Lisp code, a compiler will embed this data somehow in the FASL code.

(quote (1 2 3)) is another way to write it.

(list 1 2 3)

this is a call of the Common Lisp function LIST with three arguments 1, 2 and 3. Each of the arguments will be evaluated. Since they are numbers, they evaluate to themselves. When evaluated the result is a fresh new list (1 2 3).

Data sharing in compiled code

Imagine in a Lisp file the following four definitions:

(defparameter *list1* (list 1 2 3))
(defparameter *list2* (list 1 2 3))
(defparameter *list3* '(1 2 3))
(defparameter *list4* '(1 2 3))

Then we compile and load the file.

! (eq *list3* *list4*) now may evaluate to either T or NIL depending on the implementation and compiler settings !

Reason: in Common Lisp the Lisp compiler may share structure of literal lists (!) if they are similar. The compiler detects that here the lists are similar and will allocate only one list. Both variables *list1* and *list2* the will point to this one list.

All other EQ (object equality) comparisons of two of the above lists will return NIL.

Notations for some other data structures:

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

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

'#S(FOO :a 1 :b 2)  and (make-foo :a 1 :b 2)   ; structure

One is the literal data and the other is a function call that constructs such a data structure.

盛夏尉蓝 2024-10-03 22:15:54

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

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

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

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

(list (+ 1 2) 3)     -->  (3 3)
(quote ((+ 1 2) 3))  -->  ((+ 1 2) 3)

Quoted lists (e.g. '(1 2 3)) should be treated carefully (generally as read-only). (see SO answers When to use 'quote in Lisp and When to use 'quote in Lisp).

(list 1 2 3) will "cons" up a fresh list, independent of all others.

You can see an example of a pitfall of using quoted lists in the manual for nconc.

And, as you probably know, when you call 'list - the arguments will obviously be evaluated versus the contents of a quoted list. And 'quote takes a single argument, versus 'lists variable number of arguments.

(list (+ 1 2) 3)     -->  (3 3)
(quote ((+ 1 2) 3))  -->  ((+ 1 2) 3)
想你的星星会说话 2024-10-03 22:15:54

它们的关系类似于使用“函数名称”和“funcall”进行函数调用。

当您不知道在运行时将获得什么函数时,您可以使用funcall

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


对于像我这样因为反引号的存在而感到困惑并默认将其视为引用的人。

反引号不是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)))

Their relation can be analogous to function invocation with 'function name' and funcall.

When you have no idea what function you'll get at runtime, you use funcall.

When you have no idea what element you may get at runtime, your use list.


For people like me who get confused because of existence of backquote and count it as quote tacitly.

backquote is not quote

It's a reader-macro that expands into quote, list or others:

(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)))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文