我正在准备考试,我注意到了这个问题:
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。
我到底错过了什么?那么正确的答案是什么?
答案 0 :(得分:7)
我们可以获得car
和cdr
的内容不是列表。这是对。
使用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)
只会比较两个对象x
和y
的位置(地址)。这意味着即使两对的内容相等,比较(eq? (cons_1 1 '()) (cons_2 1 '()))
也将返回false。