use*_*428 5 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)
Run Code Online (Sandbox Code Playgroud)
我想知道为什么两个x原子都被set-car!程序所取代(我对结果的第一个猜测是什么((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!
Run Code Online (Sandbox Code Playgroud)
为什么x第一个例子中的两个都被替换了?
在第一个示例中,您有与此等效的内容:
(define cell (cons 'x null))
(define q (cons cell cell))
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,该位置只有一个 cons单元格,该单元格在结果列表结构的两个不同部分中共享。当您执行时,单个单元格中的内容将被替换为共享它的所有部分中的内容。请记住,两个单元格实际上是相同的,我们将从以下开始:xcar(set-car! (cdr q) 'y)xy(cons 'x null)
(cons (cons 'x null) (cons 'x null))
; '((x) x)
Run Code Online (Sandbox Code Playgroud)
对此:
(cons (cons 'y null) (cons 'y null))
; '((y) y)
Run Code Online (Sandbox Code Playgroud)
对于第二个示例,适用相同的考虑因素(所有三个(cons 'x null)单元实际上是共享的同一个单元),但您要替换整个cons单元,所以基本上我们将从以下开始:
(cons (cons 'x null) (cons (cons 'x null) (cons 'x null)))
; '((x) (x) x)
Run Code Online (Sandbox Code Playgroud)
对此:
(cons (cons 'x null) (cons 'y (cons 'x null)))
; '((x) y x)
Run Code Online (Sandbox Code Playgroud)
为了证明我的观点,即问题中的两个示例都展示了相同的情况,请执行以下表达式:
(define q2 (mk-q2))
(set-car! (cadr q2) 'y) ; notice the extra `a`
q2
=> '((y) (y) y)
Run Code Online (Sandbox Code Playgroud)