views:

115

answers:

4

I'm kinda confused.....

(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?

+6  A: 

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
Skeptic
+1  A: 

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)
Greg Harman
A: 

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.

Lajla
A: 

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)
dimvar