Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

set-car! and let in scheme language

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?

like image 709
user1453428 Avatar asked Oct 07 '22 13:10

user1453428


1 Answers

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)
like image 165
Óscar López Avatar answered Oct 13 '22 10:10

Óscar López