我在使用Scheme和列表的一个项目中注意到了这种半怪异的行为.我设法将行为隔离到一个部分.代码是:
(define x (list 1 2 3)) (define y (list 4 5)) (define z (cons (car x) (cdr y))) (define w (append y z)) (define v (cons (cdr x) (cdr y))) (set-car! x 6) (set-car! y 7) (set-cdr! (cdr x) (list 8)) x y z w v
给我们的输出:
(6 2 8) (7 5) (1 5) (4 5 1 5) ((2 8) 5)
任何人都可以向我解释:
为什么不(set-car! x 6)
更新Z
?因为根据我的理解car
/ cdr
返回指针或引用相应的值.这真的很奇怪,我有点困惑.
如果car
/ cdr
不返回引用/指针,那么最终如何set-cdr!
操作列表v
?
有任何想法吗?这是一个简单的修复,但我更好奇为什么变量的奇怪性正在发生.
好的,让我们逐行完成你的程序.我也为每个新创建的对象分配唯一的数字(将它们视为对象地址,如果你习惯使用类C语言),这样你就可以看到它是什么了.:-)
(define x (list 1 2 3)) ; => #1 = (1 . #2), #2 = (2 . #3), #3 = (3 . ()) (define y (list 4 5)) ; => #4 = (4 . #5), #5 = (5 . ()) (define z (cons (car x) (cdr y))) ; => #6 = (1 . #5) (define w (append y z)) ; => #7 = (4 . #8), #8 = (5 . #6) (define v (cons (cdr x) (cdr y))) ; => #9 = (#2 . #5) (set-car! x 6) ; => #1 = (6 . #2) (set-car! y 7) ; => #4 = (7 . #5) (set-cdr! (cdr x) (list 8)) ; => #2 = (2 . #10), #10 = (8 . ())
现在,让我们看看你的值(对于每个引用,使用最后指定的值):
x ; #1 => (6 . #2) => (6 . (2 . #10)) => (6 2 8) y ; #4 => (7 . #5) => (7 5) z ; #6 => (1 . #5) => (1 5) w ; #7 => (4 . #8) => (4 . (5 . #6)) => (4 . (5 . (1 . #5))) => (4 5 1 5) v ; #9 => (#2 . #5) => ((2 . #10) 5) => ((2 8) 5)
编辑:我正在添加一个图表来解释我的答案,因为你不能在评论中有图表.我没有时间制作显示上述值的图表,但这有希望解释一些事情.
每对有两个"槽",car
以及cdr
,表示如上述图中的左和右框.如您所见,每个插槽都有三个可能的东西:
的原子(在示例的数目,或在图中的符号,如let
,s5
和sqrt
)
参考(在图中表示为箭头)
Null(在图中表示为黑框)
您可以将其中任何一个放入任何插槽中.因此,在我上面的解释中,每个#
项目都是箭头,每个非#
数字都是一个原子,每个()
都是一个黑盒子.所以,在线
(define v (cons (cdr x) (cdr y)))
你正在创建一对,其中左侧插槽的内容与右侧插槽的内容相同x
(即箭头转到第2对),右侧插槽的内容与右侧插槽的内容相同的y
(箭头要配对5).换句话说,两个框都v
包含箭头,每个箭头都有一对不同的箭头.
希望这更有意义.:-)