Lisp 设置汽车!并引入方案语言

Lisp 设置汽车!并引入方案语言,lisp,scheme,racket,mit-scheme,Lisp,Scheme,Racket,Mit Scheme,这个例子的结果让我有点困惑: (define mk-q (lambda () (let ([l '(x)]) (cons l l)))) (define q (mk-q)) q => ((x) x) (set-car! (cdr q) 'y) => ((y) y) 我想知道为什么x两个原子都被set车取代了过程(我对结果的第一个猜测是((x)y)) 例如: (define mk-q2 (lambda () (let ([l '(x)])

这个例子的结果让我有点困惑:

(define mk-q
  (lambda ()
    (let ([l '(x)])
      (cons l l))))


(define q (mk-q))

q
=> ((x) x)

(set-car! (cdr q) 'y)
=> ((y) y)
我想知道为什么
x
两个原子都被
set车取代了过程(我对结果的第一个猜测是
((x)y)

例如:

(define mk-q2
  (lambda ()
    (let ([l '(x)])
      (cons l (cons l l)))))

(define q2 (mk-q2))
(set-car! (cdr q2) 'y)
=> ((x) y x) which fits my understanding of set-car!

为什么第一个示例中的
x
s都被替换了?

在第一个示例中,您有与此等效的内容:

(define cell (cons 'x null))
(define q (cons cell cell))
如您所见,在
car
位置上,只有一个
cons
单元格具有
x
,在结果列表结构的两个不同部分中共享。当您执行
(set car!(cdr q)'y)
时,单个单元格中的
x
将被共享的所有部分中的
y
替换。请记住,两个
(cons'x null)
单元格实际上是相同的,我们从这里开始:

(cons (cons 'x null) (cons 'x null))
; '((x) x)
(cons (cons 'x null) (cons (cons 'x null) (cons 'x null)))
; '((x) (x) x)
为此:

(cons (cons 'y null) (cons 'y null))
; '((y) y)
(cons (cons 'x null) (cons 'y (cons 'x null)))
; '((x) y x)
对于第二个示例,同样的考虑也适用(所有三个
(cons'x null)
单元格实际上是共享的同一个单元格),但您要替换一个完整的
cons
单元格,因此基本上我们从这一点出发:

(cons (cons 'x null) (cons 'x null))
; '((x) x)
(cons (cons 'x null) (cons (cons 'x null) (cons 'x null)))
; '((x) (x) x)
为此:

(cons (cons 'y null) (cons 'y null))
; '((y) y)
(cons (cons 'x null) (cons 'y (cons 'x null)))
; '((x) y x)
为了证明我的观点,即问题中的两个示例演示了相同的情况,请执行以下表达式:

(define q2 (mk-q2))
(set-car! (cadr q2) 'y) ; notice the extra `a`
q2
=> '((y) (y) y)

因为cons单元格本质上是指向值的两个指针。编写
(cons l)
时,创建了指向同一对象的两个指针。当你更改对象时,两个条目仍然指向同一个对象。我最初将其误读为set carl,这在某种程度上是一种有趣的方式。