方案:与集合混淆!
我很困惑这段代码是如何工作的:
(define m (list 1 2 3 '(5 8)))
(let ((l (cdr m)))
(set! l '(28 88))) ==>(1 2 3 (5 8))
(define o (list 1 2 3 '(5 8)))
(let ((l (cdr o)))
(set-car! l '(28 88))) ==> (1 (28 88) 3 (5 8))
为什么 (set! l '(28 88)))
不更新 m
?
I'm confused how this code works:
(define m (list 1 2 3 '(5 8)))
(let ((l (cdr m)))
(set! l '(28 88))) ==>(1 2 3 (5 8))
(define o (list 1 2 3 '(5 8)))
(let ((l (cdr o)))
(set-car! l '(28 88))) ==> (1 (28 88) 3 (5 8))
Why does (set! l '(28 88)))
not update m
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
放!不能改变列表(或任何其他结构,与 set-car/cdr 不同!),但只能更改 a (在您的情况下,本地l)变量的绑定。
set! can't mutate a list (or any other structure, unlike set-car/cdr!), but only change the binding of a (in your case, the local l) variable.
根据怀疑论者的回答, l 是一个本地绑定变量,并通过 set 更改它!不会对 m 做任何事。
如果您希望第一个 let 返回预期值,则需要通过返回本地绑定 l 的新值来进行后续操作,如下所示:
As per skeptic's answer, l was a locally-bound variable, and changing it via set! is not going to do anything to m.
If you want the first let to return the expected value, you need to follow-up by returning the new value of the locally-bound l, like so:
set!
仅更改符号的绑定,通常让垃圾收集器消耗其原始值。它不会改变数据,而是重新绑定符号。因此,像(set! (car '(symbol symbol2)) 3)
这样的东西不起作用,即使第二个子表单计算为符号值。要真正改变内存中的数据,可以使用
set-car!
、set-cdr!
、set-vector!
等形式之一必须使用。它们具有完全不同的语义,并且确实评估其第二个子形式,并且无论其评估的数据是什么,都会在内存中更新,从而更改与其共享该内存的所有其他符号的值。set!
only changes the binding of a symbol, often letting the garbage collector consume its original value. It doesn't mutate data, it rebinds a symbol. Hence things like(set! (car '(symbol symbol2)) 3)
don't work, even though the second subform evaluates to a symbol-value.To truly mutate data in-memory, one of the forms of
set-car!
,set-cdr!
,set-vector!
et cetera have to be used. These have completely different semantics and do evaluate their second sub-form, and what-ever data it evaluates to is then updated in-memory, changing all other symbol's value that share that memory with it.这与变异与重新绑定无关。
set!
和set-car!
都会更改指针。在您的示例中,l
最初指向该对的cdr
,它也是一对。当你设置时! l
,您告诉它指向保存'(28 88)
的新位置。类似地,当您执行
set-car!
时,您是在说car
指针现在将指向位置 B 而不是其当前位置 A,但 A 的内容是没有变异。例如:It's not about mutating vs rebinding. Both
set!
andset-car!
change pointers. In your example,l
initially points to thecdr
of the pair, which is also a pair. When youset! l
, you're telling it to point to the new location which holds'(28 88)
.Similarly, when you do
set-car!
you are saying that thecar
pointer will now point to a location B instead of its current location A, but the contents of A aren't mutated. For example: