SICP 中不一致的方框指针图

Inconsistent box-and-pointer diagrams in SICP

计算机程序的结构和解释 (SICP) 图 3.16 和 3.17 中的方框指针图看起来并不等同(纯粹关于值,而不是内存),尽管它说它们是等同的。 ("When thought of as a list, z1 and z2 both represent "相同的“列表,((a b) a b))”,第 258 页)

(define x (list 'a 'b))
(define z1 (cons x x))
(define z2 (cons (list 'a 'b) (list 'a 'b)))

SICP 像这样绘制 z1 对:

和 z2 是这样的:

这对 z1 中的箭头似乎并没有指向整对 x。他们甚至没有指向同一件事,尽管他们都收到了相同的(内存和价值)对。 我会将第一个图表评估为 (a b),将第二个评估为 ((a b) a b)

我猜每个箭头实际上都指向整对,x,但在第 98 页的图 2.3 中:

通过指向侧面或两个项目之间,它非常清楚地指向整个框。

我对方框指针图的理解有误还是完全不同?

你读的太多了。 :-) 如果它指向方框 anywhere,则假定它是指向该 cons 单元格的指针。您不能具体指向它的 carcdr 部分。

你最后的假设是正确的。点表示指针值的位置,箭头指向的整个双框是目标。它指向侧面、中上、左上或右上都没有关系。对象的 "address" 是整对。

如果不使用 carcdr 访问对象的一部分,则无法指向对象的一部分。你这样做的第二个你拥有它所指向的任何东西而不是间接指针。 (car '(a b)) ; ==> aa 在被垃圾回收之前没有任何仍然指向它的列表的本质。

我们可以这样说明:

[=#1|#3|#2]
[=#2|#3|()] 
[=#3|a |#4]
[=#4|b |()]

带 =# 的第一个值是框本身的位置,而接下来的两个值是 carcdr。上面,x 指向地址#3,z1 指向#1。让我们z2

[=#5|#6|#8]
[=#6|a |#7] 
[=#7|b |()] 
[=#8|#9|()]
[=#9|a |#10]
[=#10|b |()]

如您所见,z2 使用的 consz1 多两个,因为它不重用同一个对象作为其列表的两个元素,而是使用单独的类似 -寻找列表。

在图中,z1carcdr都指向同一个列表xz2 指向两个不同的列表,但这些列表中的元素是相同的。

这是因为符号是单例的。因此,a 只有一个符号对象,在两个不同的地方计算 'a 将指向同一个 a。其他单例是 #f#t()

cons 总是创建一个新的对,list 只是一个将参数 cons 组合在一起的过程。因此,相同的代码 (list 'a 'b) 表达式中的两个位置使两个不同的对象看起来相同。

(eq? (car z1) (cdr z1))    ; ==> #t same object
(eq? (car z2) (cdr z2))    ; ==> #f not same object
(equal? (car z2) (cdr z2)) ; ==> #t they look the same, but they are not the same. (created at different places)

引用的数据可以看成是在程序启动前一次性创建的。因此这是未定义的。

(eq? '(a b) '(a b))         ; ==> #t or #f (undefined)
(eq? '(b c) (cdr '(a b c))) ; ==> #t or #f (undefined)

原因是 Scheme 被允许(但不是必须)以与结构 z1 相同的方式重用数据。