tags:

views:

370

answers:

3

Okay i noticed this semi weridish behavior in one of my projects using scheme, and lists. I managed to isolate the behavior, into a single section. The code is:

(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

Gives us the output of:

(6 2 8)
(7 5)
(1 5)
(4 5 1 5)
((2 8) 5)

Can anyone explain to me:

  1. Why does (set-car! x 6) not update Z? Since according to my understanding car/cdr return pointers or references to the corresponding values. This is really werid and im kinda confused.
  2. If car/cdr does not return references/pointers then how is the final set-cdr! manipulating the list v?

Any ideas? Its a simple fix, but im more curious as to why the weridness with the variables is going on.

+4  A: 

(define z (cons (car x) (cdr y))) has allocated a new cons cell for the head of z. The head of x is a different cons cell to the head of z, so changing the contents of this cons cell for x does not change z.

David Plumpton
If you assume that, then why does set-cdr! manipulate v?
UberJumper
uberjumper: It doesn't. It manipulates the cons cell that the cdr of x points to, which is the same as the one that the car of v points to. v itself remains unchanged, as does x (by the set-cdr! call, I mean).
Matthias Benkard
+10  A: 
Chris Jester-Young
Can you explain more related to V? Why does cons part for Z return values(#6), but cons of (cdr x)(cdr y) (#9) still be bound to two references?
UberJumper
both z and v are defined as the cons of two existing values; but the car of z is a number (immutable value), while the car of v is a cons cell (mutable value, shared). set-car! and set-cdr! modify cons cells, not the values they hold.
Javier
+1 for the diagram. What did you use to make that?
Kyle Cronin
Xfig (http://www.xfig.org/). :-)
Chris Jester-Young
+2  A: 

remember that each variable doesn't hold a list, they hold just a cons cell. a list (or a tree) is a composite structure of several cons cells, some of which may be shared between several structures.

also, you're thinking about pointers and references, instead of thinking about values, which can be either immutable values (like numbers, or symbols) or mutable values (like conses or strings) mutable values are allocated, garbage collected and passed by reference.

one last point to remember: the cons procedure always allocates a new cons cell.

after (define z (cons (car x) (cdr y))), z holds a brand new cons with the same as x and the same car as x, and the same cdr as y. when you (set-car! x), you just change the x cons cell, not z.

after (define v (cons (cdr x) (cdr y))), v holds a brand new cons whose car is the same value as the cdr of x; that is a cons cell. the very same cons cell as (cdr x). it's shared by the two lists. when that shared cons cell is modified by (set-cdr! (cdr x) ...), both lists are affected.

Javier