lisp 中的列表比较与数字比较(值和对象)

Comparison of lists in lisp vs Comparison of numbers(value and objects)

我无法理解如何按值比较数字与按地址比较数字。 我尝试了以下方法:

(setf number1 5)
(setf number2 number1)
(setf number3 5)
(setf list1 '(a b c d) )
(setf list2 list1)
(setf list3 '(a b c d) )

然后我使用了以下谓词函数:

>(eq list1 list2) T
>(eq list1 list3) Nil
>(eq number1 number2) T
>(eq number1 number3) T

为什么列表 eq 表现得像它应该的那样(list1 和 list3 的指针都不同)但是对于数字它却不像我认为的那样表现,因为 number1 和 number3 应该有不同的地址。因此,我的问题是为什么这不像我认为的那样起作用,以及是否有一种方法可以比较包含数字和值的变量的地址。

Common Lisp 中的相等谓词

how to compare numbers by value vs by address.

虽然在某种意义上可以应用,但这并不是 Common Lisp 提供的真正模型。阅读内置相等谓词有助于阐明对象在内存中的存储方式(隐式)..

EQ 通常是检查 "same address" 的内容,但这不是指定的方式,也不完全是它的作用。它"returns true if its arguments are the same, identical object; otherwise, returns false."

同一个物体是什么意思?对于诸如 cons-cells(从中构建列表)之类的东西,内存中某处有一个对象,eq 检查两个值是否是同一个对象。请注意,eq 可以 return true or false 在像数字这样的基元上,因为实现可以自由地复制它们。

EQL 类似于 eq,但它为数字和字符添加了一些额外的条件。相同类型和值的数字保证是 eql,代表相同字符的字符也是如此。

EQUAL and EQUALP 是事情开始变得更复杂的地方,你实际上得到了诸如列表的逐元素比较之类的东西。

这个具体案例

Why is it that with lists eq acts like it should (both pointers for list1 and list3 are different) yet for numbers it does not act like I think it should as number1 and number3 should have different addresses. Thus my question is why this doesn't act like I think it should and if there is a way to compare addresses of variables containing numbers vs values.

eq 文档中的示例表明 (eq 3 3)(因此,(让((x 3) (y 3)) (eq x y)) 可以 return 为真 为假。您现在观察到的行为不是唯一可能的。

另请注意,在编译代码中,常量值可以合并为一个。这意味着编译器可以选择使以下 return 为真:

(let ((x '(1 2 3))
      (y '(1 2 3)))
   (eq x y))

其中一个问题是在特定设置的一个实现中测试它并不能告诉你太多。当 ANSI Common Lisp 规范允许时,实现的行为可能会有所不同。

  1. 不要假设两个相同值的数字是EQ或不是EQ。这在 Common Lisp 中未指定。使用 EQL= 比较数字。

  2. 不要假设两个在打印表示中看起来相似的文字列表是 EQ 或不是 EQ。对于一般情况,这在 Common Lisp 中未指定。

例如:

包含以下内容的文件:

(defvar *a* '(1 2 3))
(defvar *b* '(1 2 3))

如果现在编译并加载文件,则未指定 (eq *a* *b*)T 还是 NIL。 Common Lisp 允许优化编译器检测列表具有相似的内容,然后将只分配一个列表,并且两个变量将绑定到同一个列表。

当并非所有列表都具有相似内容时,实现甚至可以节省 space。例如,在 (a 1 2 3 4)(b 1 2 3 4) 中可以共享一个子列表 (1 2 3 4)

对于包含大量列表数据的代码,这有助于节省 space 代码和内存。其他实现可能没有那么复杂。在交互式使用中,实现不太可能像那样尝试保存 space。

在 Common Lisp 标准中,相当多的行为是未指定。预计具有不同目标的实施可能会受益于不同的方法。