gpt4 book ai didi

lisp - 在 Common Lisp 中通过对象引用传递

转载 作者:行者123 更新时间:2023-12-04 22:34:18 25 4
gpt4 key购买 nike

Peter Seibel 在 Practical Common Lisp 中写道,“至少在概念上,Common Lisp 中的所有值都是对对象的引用。”

我用下面的代码尝试了这个概念:

(setf x 5)
(setf y x)
(print x) % output: x is 5
(print y) % output: y is 5
(setf x 6)
(print x) % output: x is 6
(print y) % output: y is 5

如果 Lisp 是按对象引用传递的,y 应该指向 x,因此将 x 更改为 6 也应该将 y 更改为 6。但事实并非如此。看起来 Lisp 是按对象值传递的。谁能帮忙解释一下发生了什么?

最佳答案

小整数在 Lisp 实现中通常不是引用。在 Common Lisp 中说所有值都是引用是不正确的。在怀疑值是引用的情况下编程通常是更安全的假设,更符合编写正确的代码。

但是,您的示例与作为引用实现的小整数一致。这并不能证明它们不是。

如果一个变量x持有一个整数,如 5 , 然后我们分配给 x(setf x 4) , 我们没有改变对象 5进入4 .我们正在改变变量绑定(bind) x : 我们已经覆盖了 5以前在 x 中的值使用新值 4 .

即使我们使用正引用到堆中的对象,如 cons 单元,这也会起作用:

(setf x '(1 . 2))
(setf y x)
y -> (1 . 2)
(setf x '(4 . 5))
y -> (1 . 2)

xy是自变量,并且独立地保存对 cons 单元格的引用。 x最初持有对 (1 . 2) 的引用目的。我们分配 xy ,所以现在 y还持有对 (1 . 2) 的引用.它有自己的引用副本。那么当我们分配 (4 . 5) 时, x的引用被对 (4 . 5) 的引用覆盖,但是 y不受影响。为什么会这样?

我们如何证明 conses 使用引用语义是通过改变单元格本身:

(setf x (cons 1 2)) ;; we better not use a literal any more!
x -> (1 . 2)
(setf y x)
y -> (1 . 2)

;; now mutate

(rplaca x 10)
(rplacd x 20)

x -> (10 . 20)
y -> (10 . 20)

自从改变存储在 x 中的单元格使突变出现在存储在 y 中的单元格上,我们知道 xy必须持有对同一对象的引用。

问题来了:我们不能用整数来执行这个测试,因为整数是不可变的!没有类似rplaca的功能这将破坏代表 1 的实际位, 并将它们变成 10 .

eq函数没有帮助,因为它所能做的就是确认这两个值是同一个对象:

(setf x 5)
(setf y x)

(eq x y) -> ?

如果这个eq调用返回 T , 然后 xy是同一个对象。我说 if 是因为 ANSI Common Lisp 让这个实现特定化。允许实现产生 NIL !

但是,它会产生 T在将小整数(fixnums)直接打包到一个值中的实现中,而不是指向装箱堆对象的指针(流行的实现方法)。也就是说,像 4 这样的值在它出现的任何地方都被认为是一个对象,即使它是通过复制一个包含表示 4 的位模式的值来传播的。直接。

因此或多或少归结为您只需要知道您的实现是如何工作的就可以确定哪些类型的对象是引用。

关于lisp - 在 Common Lisp 中通过对象引用传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62235018/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com