我对此代码的工作原理感到困惑:
(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
?
答案 0 :(得分:7)
设置!不能改变列表(或任何其他结构,不像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
答案 1 :(得分:1)
根据怀疑论者的回答,l是一个本地绑定变量,并通过set更改它!我不会做任何事情。
如果您希望第一个让我们返回预期值,您需要通过返回本地绑定的l的新值来跟进,如下所示:
(define m (list 1 2 3 '(5 8)))
(let ((l (cdr m)))
(set! l '(28 88))
l)
(28 88)
答案 2 :(得分:1)
set!
仅更改符号的绑定,通常让垃圾收集器使用其原始值。它不会改变数据,它会重新绑定符号。因此,(set! (car '(symbol symbol2)) 3)
之类的东西不起作用,即使第二个子表单求值为符号值。
要真正改变内存中的数据,必须使用set-car!
,set-cdr!
,set-vector!
等形式之一。它们具有完全不同的语义,并且会评估它们的第二个子表单,然后在内存中更新它评估的数据,更改与其共享该内存的所有其他符号的值。
答案 3 :(得分:0)
这不是关于变异与重新绑定。 set!
和set-car!
都会改变指针。在您的示例中,l
最初指向该对的cdr
,这也是一对。当您set! 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)