测试两对(cons单元格)是否相同

时间:2012-06-08 18:20:41

标签: scheme the-little-schemer seasoned-schemer

来自经验丰富的计划器

150的第150页中的以下函数通过改变每个列表的cdr来确定两个列表是否具有相同的标识(即占用相同的内存),然后检查更改是否同时影响了两者:

(define same?
 (lambda (c1 c2)
   (let ((t1 (cdr c1))
         (t2 (cdr c2)))
     (set-cdr! c1 1)
     (set-cdr! c2 2)
     (let ((v (= (cdr c1) (cdr c2))))
       (set-cdr! c1 t1)
       (set-cdr! c2 t2)
       v))))

现在,如果我按如下方式定义a_list

(define a_list (list 'a 'b 'c 'd))

并评估

(same? a_list (cdr a_list))

函数返回#f,调试器(Dr。Racket)确认这两个列表 - 自第二个参数以来应该共享其大多数成员是第一个参数的正确子集 - 实际上有不同同一成员的副本。这怎么可能?!

略微改变这个想法:

(set-cdr! (cddr a_list) a_list)

现在a_list是周期性的。如果我用same?测试这个函数,它只在两个参数同步时注册#t,即(same? a_list a_list)(same? a_list (cdddr a_list))

[编辑答案在被接受的帖子评论链的底部]

1 个答案:

答案 0 :(得分:4)

same?函数不会检查两个列表是否共享元素。 它检查两对(即两个cons单元格)是否相同。

(define a_list (list 'a 'b 'c 'd))中你有4对。 在(same? a_list (cdr a_list))中,您检查是否第一个 和第二对是同一对,因为它们不是, same?会返回#f

关于:

  

..和调试器(Dr. Racket)确认这两个列表 - 哪个   因为第二个论点是a,所以应该分享他们的大多数成员   第一个适当的子集 - 实际上有不同的副本   同样的成员。这怎么可能?!

您能更准确地了解如何在DrRacket中查看此内容吗?

两个列表a-list和(cdr a-list)共享成员。

编辑:

假设c1c2是两个不同利弊单元的名称:

c1: (foo . bar)      c2:  (baz . qux)

现在我们评估(set-cdr! c1 1)并获取:

c1: (foo . 1)      c2:  (baz . qux)

现在我们评估(set-cdr! c2 2)并获取:

c1: (foo . 1)      c2:  (baz . 2)

然后我们将cdrs(= (cdr c1) (cdr c2))进行比较。 由于cdrs不同,我们得到#f

结论:当cons细胞不同时,相同?返回#f。


现在假设c1c2是同一个缺点单元格的名称:

c1 = c2: (foo . bar)

现在我们评估(set-cdr! c1 1)并获取:

c1 = c2: (foo . 1)  

现在我们评估(set-cdr! c2 2)并获取:

c1 = c2: (foo . 2)  

然后我们将cdrs(= (cdr c1) (cdr c2))进行比较。 由于cdrs相同,我们得到#t

结论:当缺点单元格相同时,same?会返回#f

编辑2

检查cons小区c是否是其中之一 l的cons细胞使用此:

(define (loop c l)
  (cond
    [(null? l) #f]
    [(same? c l) #t]
    [else (loop c (cdr l))]))