方案:与集合混淆!

发布于 2024-09-04 09:52:18 字数 302 浏览 4 评论 0原文

我很困惑这段代码是如何工作的:

(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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

三生路 2024-09-11 09:52:18

放!不能改变列表(或任何其他结构,与 set-car/cdr 不同!),但只能更改 a (在您的情况下,本地l)变量的绑定。

(define x 3)
(define f (lambda (x) (set! x 4)))
(define g (lambda (y) (set! x y)))
(f x)
x 
-> 3
(g 5)
x
-> 5

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.

(define x 3)
(define f (lambda (x) (set! x 4)))
(define g (lambda (y) (set! x y)))
(f x)
x 
-> 3
(g 5)
x
-> 5
花间憩 2024-09-11 09:52:18

根据怀疑论者的回答, l 是一个本地绑定变量,并通过 set 更改它!不会对 m 做任何事。

如果您希望第一个 let 返回预期值,则需要通过返回本地绑定 l 的新值来进行后续操作,如下所示:

(define m (list 1 2 3 '(5 8)))
(let ((l (cdr m)))
(set! l '(28 88))
  l)

(28 88)

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:

(define m (list 1 2 3 '(5 8)))
(let ((l (cdr m)))
(set! l '(28 88))
  l)

(28 88)
败给现实 2024-09-11 09:52:18

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.

じее 2024-09-11 09:52:18

这与变异与重新绑定无关。 set!set-car! 都会更改指针。在您的示例中,l 最初指向该对的 cdr,它也是一对。当你设置时! l,您告诉它指向保存 '(28 88) 的新位置。

类似地,当您执行 set-car! 时,您是在说 car 指针现在将指向位置 B 而不是其当前位置 A,但 A 的内容是没有变异。例如:


(define list1 '(2 3)) 
(define list2 (list 72 list1 55))
(set-car! (cdr list2) 99)

list1 ==> '(2 3) 
list2 ==> '(72 99 55)

It's not about mutating vs rebinding. Both set! and set-car! change pointers. In your example, l initially points to the cdr of the pair, which is also a pair. When you set! 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 the car pointer will now point to a location B instead of its current location A, but the contents of A aren't mutated. For example:


(define list1 '(2 3)) 
(define list2 (list 72 list1 55))
(set-car! (cdr list2) 99)

list1 ==> '(2 3) 
list2 ==> '(72 99 55)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文