2

来自Seasoned Schemer的 pg 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))

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

4

1 回答 1

4

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

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

关于:

.. 并且调试器(Racket 博士)确认这两个列表——它们应该共享它们的大部分成员,因为第二个参数是第一个参数的真子集——实际上确实具有相同成员的不同副本。这怎么可能?!

您能否更准确地了解如何在 DrRacket 中检查这一点?

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

编辑:

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

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是同一个 cons 单元格的名称:

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.

结论:当 cons 单元格相同时,same?返回#f.

编辑 2

要检查 cons 单元格是否是使用这个c的 cons 单元格之一l

(define (loop c l)
  (cond
    [(null? l) #f]
    [(same? c l) #t]
    [else (loop c (cdr l))]))
于 2012-06-08T18:45:52.060 回答