5

I am little bit confused by the result of this example:

(define mk-q
  (lambda ()
    (let ([l '(x)])
      (cons l l))))


(define q (mk-q))

q
=> ((x) x)

(set-car! (cdr q) 'y)
=> ((y) y)

I am wondering why both x atoms have been replaced by set-car! procedure (my first guess for what the result would be was ((x) y))?

For example:

(define mk-q2
  (lambda ()
    (let ([l '(x)])
      (cons l (cons l l)))))

(define q2 (mk-q2))
(set-car! (cdr q2) 'y)
=> ((x) y x) which fits my understanding of set-car!

Why are both xs in the first example replaced?

Sam Tobin-Hochstadt
  • 4,983
  • 1
  • 21
  • 43
user1453428
  • 185
  • 2
  • 8
  • 2
    Because a cons cell is essentially two pointers to values. When you write `(cons l l)` you create two pointers to the same object. When you change the object, both entries still point to the same object. – Chris Taylor Jun 13 '12 at 11:06
  • I initially misread this as set-carl, which was amusing in an aqua teen hunger force sort of way. – BillRobertson42 Jun 18 '12 at 03:15

1 Answers1

4

In the first example, you have something equivalent to this:

(define cell (cons 'x null))
(define q (cons cell cell))

As you can see, there's only one cons cell with x at the car position, that is being shared in two different parts of the resulting list structure. When you execute (set-car! (cdr q) 'y) the x in the single cell gets replaced by y in all the parts where it's being shared. Remembering that both (cons 'x null) cells are really the same, we're going from this:

(cons (cons 'x null) (cons 'x null))
; '((x) x)

to this:

(cons (cons 'y null) (cons 'y null))
; '((y) y)

For the second example the same considerations apply (all three (cons 'x null) cells are actually the same one being shared), but you're replacing a whole cons cell, so basically we're going from this:

(cons (cons 'x null) (cons (cons 'x null) (cons 'x null)))
; '((x) (x) x)

to this:

(cons (cons 'x null) (cons 'y (cons 'x null)))
; '((x) y x)

To prove my point that both of the examples in the question demonstrate the same situation, execute this expressions:

(define q2 (mk-q2))
(set-car! (cadr q2) 'y) ; notice the extra `a`
q2
=> '((y) (y) y)
Óscar López
  • 232,561
  • 37
  • 312
  • 386