SICP中的盒子和指针图表不一致

Aar*_*ron 8 lisp scheme sicp

计算机程序的结构和解释(SICP)的图3.16和3.17中的方框图和指针图看起来并不相同(纯粹是关于价值,而不是记忆),尽管它们是这样的.("当被认为是一个列表,z1并且z2都代表"相同"列表时,((a b) a b))",第258页)

(define x (list 'a 'b))
(define z1 (cons x x))
(define z2 (cons (list 'a 'b) (list 'a 'b)))
Run Code Online (Sandbox Code Playgroud)

SICP像这样绘制对z1:

在此输入图像描述

和z2像这样:

在此输入图像描述

这对中的箭头z1似乎都没有指向整个对,x.他们甚至没有指出相同的事情,尽管两者都收到了相同的(记忆和价值)对.我会将第一个图表评估为(a b),而第二个图表评估为((a b) a b)

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

在此输入图像描述

通过指向侧面或两个项目之间非常清楚地指向整个盒子.

我是否错误地理解了盒子和指针图或其他完全不同的东西?

Chr*_*ung 10

你读得太多了.:-)如果它指向任何地方的框,假设它是指向该cons单元格的指针.你不能明确指向carcdr它的一部分.

  • Scheme(和Lisp)不是C; 它本身没有地址.它具有对象引用,它(概念上)总是指整个对象,而不是其中的一部分.因此,对cons单元的对象引用是指整个cons单元(即使它通常被实现为指向cons单元的起始位置的指针),对字符串的对象引用是指整个字符串(而不是字符串中的单个字符),对矢量的对象引用是指整个矢量等. (4认同)

Syl*_*ter 6

你最后的假设是正确的.点表示指针值的位置,箭头指向的整个双框是目标.如果它指向侧面,顶部中间,左上角或右上角并不重要.它是整个对,它是对象的"地址".

如果没有使用car和访问它的部分,则无法指向对象的一部分cdr.第二个你这样做,你有任何指向,而不是间接指针.(car '(a b)) ; ==> a并且a没有任何列表的精华仍然指向它,直到它被垃圾收集.

我们可以这样说明:

[=#1|#3|#2]
[=#2|#3|()] 
[=#3|a |#4]
[=#4|b |()]
Run Code Online (Sandbox Code Playgroud)

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

[=#5|#6|#8]
[=#6|a |#7] 
[=#7|b |()] 
[=#8|#9|()]
[=#9|a |#10]
[=#10|b |()]
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,z2使用两个以上cons,z1因为它不会将同一个对象重用为其列表的两个元素,而是使用单个类似的相似列表.

在附图中,都carcdrz1指向同一个列表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)
Run Code Online (Sandbox Code Playgroud)

引用的数据可以看作是在程序启动之前一次创建的.因此,这是未定义的.

(eq? '(a b) '(a b))         ; ==> #t or #f (undefined)
(eq? '(b c) (cdr '(a b c))) ; ==> #t or #f (undefined)
Run Code Online (Sandbox Code Playgroud)

原因是Scheme允许(但没有义务)以与结构相同的方式重用数据z1.