Question

I'm confused about destructive operations in Scheme. Let's say I have a list and some destructive procedures defined in the global environment:

(define a '(a b c))
(define (mutate-obj x)
    (set! x '(mutated)))
(define (mutate-car! x)
    (set-car! x 'mutated))
(define (mutate-cdr! x)
    (set-cdr! x 'mutated))

Then we have the following expression evaulation:

(mutate-obj! a) a => (a b c)
(mutate-car! a) a => (mutated b c)
(mutate-cdr! a) a => (mutated . mutated)

Why isn't set! having an effect on a outside its procedure when both set-car! and set-cdr! have? Why isn't the expression on the first line evaluating to (mutated)? How does all of this really work?

Was it helpful?

Solution

The first example isn't working as you imagined. Although both the x parameter and the a global variable are pointing to the same list, when you execute (set! x '(mutated)) you simply set x (a parameter local to the procedure) to point to a different list, and a remains unchanged. It'd be different if you wrote this:

(define (mutate-obj)
  (set! a '(mutated)))

Now a gets mutated inside the procedure. The second and third procedures are modifying the contents of the a list, also pointed by x, so the change gets reflected "outside" once the procedure returns.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top