为什么这两个不相等?

时间:2016-05-28 23:48:11

标签: scheme racket

我正在准备考试,我注意到了这个问题:

Define an object x so that (eq? (car x) (cdr x)) returns #t

我最初认为这很简单。 cdr x是一个列表,car x是一个单独的元素,所以我的猜测就是让x中的第一个元素成为一个等于x尾的列表。所以我想出了

(define x (list (list 1) 1))

在DrRacket中调用car x会产生(list 1)cdr x也是如此,但当我尝试调用(eq? (car x) (cdr x))时,结果为#f。

我到底错过了什么?那么正确的答案是什么?

3 个答案:

答案 0 :(得分:7)

我们可以获得carcdr的内容不是列表。这是

使用cons创建对,例如:

(define val (list 1))

(define val-pair (cons val val))
另一方面,

(list (list 1) 1)相当于(cons (list 1) (list 1)),其中list被称为两次,每次都会在内存中返回一个新的单独对象虽然持有相同的价值观。但eq?仅对相同的内存对象返回true。

因此,虽然你的想法是合理的,价值方面的,但这里实际比较的不是值,而是同一性,就像内存对象的“指针等式”一样。

答案 1 :(得分:4)

使用您使用(list 1)的示例:

(define x
  (let ([tail (list 1)])
    (cons tail tail)))

一个更简单的例子:

(define x '(()))    ; same as: (define x (cons (list) (list)))

这依赖于这样一个事实,即只有一个空列表对象(即,(eq? (list 1) (list 1))始终为false,(eq? (list) (list))始终为true)。

在相关的说明中(尽管在测试过程中略高于顶部),您是否知道也可以创建一个x(car x)引用的对象(cdr x)x相同的对象?

(define x (call-with-input-string "#0=(#0# . #0#)" read))

: - P

答案 2 :(得分:4)

问题是为什么

(define x (list (list 1) 1))
(eq? (car x) (cdr x))

给出结果#f

首先,让我们使用cons代替list

(list 1)    is the same as  (cons 1 '())
(list a b)  is the same as  (cons a (cons b '())

你的例子变成了:

(define x (cons (cons 1 '()) 
                (cons 1 '()))
(eq? (car x) (cdr x))

由于我们在上面两次使用表达式(cons 1 '()),所以我们可以添加索引(我们可以参考表达式。

(define x (cons (cons_1 1 '()) 
                (cons_2 1 '()))
(eq? (car x) (cdr x))

这表明

(car x) returns the result of (cons_1 1 '())
(cdr x) returns the result of (cons_2 1 '())

调用(cons a b)将在内存中分配一个小的数据结构(大致)如下所示:

<tag-for-pairs>  <pointer-to-the-value-a> <pointer-to-the-value-b>

这意味着调用(cons_1 1 '())(cons_2 1 '())将分配两对,每对将在内存中拥有自己的位置(地址)。

来电(eq? x y)只会比较两个对象xy的位置(地址)。这意味着即使两对的内容相等,比较(eq? (cons_1 1 '()) (cons_2 1 '()))也将返回false。