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 单元格的指针。您不能具体指向它的 car
或 cdr
部分。
你最后的假设是正确的。点表示指针值的位置,箭头指向的整个双框是目标。它指向侧面、中上、左上或右上都没有关系。对象的 "address" 是整对。
如果不使用 car
和 cdr
访问对象的一部分,则无法指向对象的一部分。你这样做的第二个你拥有它所指向的任何东西而不是间接指针。 (car '(a b)) ; ==> a
和 a
在被垃圾回收之前没有任何仍然指向它的列表的本质。
我们可以这样说明:
[=#1|#3|#2]
[=#2|#3|()]
[=#3|a |#4]
[=#4|b |()]
带 =# 的第一个值是框本身的位置,而接下来的两个值是 car
和 cdr
。上面,x
指向地址#3,z1
指向#1。让我们z2
[=#5|#6|#8]
[=#6|a |#7]
[=#7|b |()]
[=#8|#9|()]
[=#9|a |#10]
[=#10|b |()]
如您所见,z2
使用的 cons
比 z1
多两个,因为它不重用同一个对象作为其列表的两个元素,而是使用单独的类似 -寻找列表。
在图中,z1
的car
和cdr
都指向同一个列表x
。 z2
指向两个不同的列表,但这些列表中的元素是相同的。
这是因为符号是单例的。因此,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
相同的方式重用数据。
计算机程序的结构和解释 (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 单元格的指针。您不能具体指向它的 car
或 cdr
部分。
你最后的假设是正确的。点表示指针值的位置,箭头指向的整个双框是目标。它指向侧面、中上、左上或右上都没有关系。对象的 "address" 是整对。
如果不使用 car
和 cdr
访问对象的一部分,则无法指向对象的一部分。你这样做的第二个你拥有它所指向的任何东西而不是间接指针。 (car '(a b)) ; ==> a
和 a
在被垃圾回收之前没有任何仍然指向它的列表的本质。
我们可以这样说明:
[=#1|#3|#2]
[=#2|#3|()]
[=#3|a |#4]
[=#4|b |()]
带 =# 的第一个值是框本身的位置,而接下来的两个值是 car
和 cdr
。上面,x
指向地址#3,z1
指向#1。让我们z2
[=#5|#6|#8]
[=#6|a |#7]
[=#7|b |()]
[=#8|#9|()]
[=#9|a |#10]
[=#10|b |()]
如您所见,z2
使用的 cons
比 z1
多两个,因为它不重用同一个对象作为其列表的两个元素,而是使用单独的类似 -寻找列表。
在图中,z1
的car
和cdr
都指向同一个列表x
。 z2
指向两个不同的列表,但这些列表中的元素是相同的。
这是因为符号是单例的。因此,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
相同的方式重用数据。