计算机程序的结构和解释(SICP)图3.16和3.17中的方框图和指针图看起来并不相同(纯粹是关于价值,而不是记忆),尽管它们说的是. (“当被认为是列表时,z1和z2都代表”相同“列表,((a b)a b))”,pg. 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中:
通过指向侧面或两个项目之间非常清楚地指向整个框.
我是否错误地理解了盒子和指针图或其他完全不同的东西?
解决方法
你最后的假设是正确的.点表示指针值的位置,箭头指向的整个双框是目标.如果它指向侧面,顶部中间,左上角或右上角并不重要.它是整个对,是对象的“地址”.
如果没有使用car和cdr访问其部分,则无法指向对象的一部分.第二个你这样做,你有任何指向,而不是间接指针. (汽车'(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使用了比z1更多的缺点,因为它不会重复使用与其列表中的两个元素相同的对象,而是使用单独的类似外观的列表.
在附图中,z1的car和cdr指向相同的列表x. z2指向两个不同的列表,但这些列表中的元素是相同的.
原因是符号是单例.因此,您只有一个符号对象用于a并且评估’在两个不同的位置中的a将指向相同的a.其他单身人士是#f,#t和()
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相同的方式重用数据.