从官方文档https://www.scheme.com/tspl4/start.html#./start:h9
学习方案命令这里发生了什么:
> (define ls1 '((ignored) ignored))
#<unspecified>
> ls1
((ignored) ignored)
> (set-car! (cdr ls1) 'a)
#<unspecified>
> ls1
((ignored) a)
这是预期的。但是,当我使用另一个list
来定义&#39;看起来&#39;与ls1
一样,以下方式,为什么set-car!
会将ignored
的两次出现替换为a
?我理解define end (cons 'ignored '())
很可能是行为的原因,但我无法对此做出任何解释。
> (define end (cons 'ignored '()))
#<unspecified>
> end
(ignored)
> (define ls2 (cons end end))
#<unspecified>
> ((set-car! (cdr ls2) 'a)
#<unspecified>
> ls2
((a) a)
>
答案 0 :(得分:1)
假设你有
(define end1 (cons 'ignored '()))
(define ls1 (cons end1 (cons 'ignored '())))
(define end2 (cons 'ignored '()))
(define ls2 (cons end2 end2))
很容易看出,ls2
指的是名为end2
的相同的实体,其中包含car
和cdr
两个部分。
完全不同的是,ls1
的两个部分将每个部分引用到另一个实体 - car
引用end1
和cdr
- 指向另一个实体的结果相同的cons
形式:
(eq? end2 end2) ;=> #t
(eq? (car ls2) (cdr ls2)) ;=> #t
(eq? (car ls1) (cdr ls1)) ;=> #f
(equal? (car ls1) (cdr ls1)) ;=> #t
eq?
返回#t
表示两个参数实际上是内存中的同一个对象。因此,当您更改内存驻留对象的内容时,更改内存驻留对象的内容。使用ls2
时,只涉及一个位置,{{1}引用的位置{1}}:
end2
否则,每次(eq? (cdr ls2) end2) ;=> #t
(set-car! (cdr ls2) 'a) ; changes `end2` to '(a)
的新调用都会保证在内存中创建并返回 new 位置,即使保留cons
内容也是如此。因此,改变一个副本不会影响另一个副本,位于内存中的另一个位置:
equal?