Деструктивные операции в схематических средах

Я запутался в деструктивных операциях в Scheme. Допустим, у меня есть список и некоторые деструктивные процедуры, определенные в глобальной среде:

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

Тогда у нас есть следующая оценка выражения:

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

Почему set! не влияет на a за пределами своей процедуры, когда действуют и set-car!, и set-cdr!? Почему выражение в первой строке не равно (mutated)? Как все это работает на самом деле?


person Community    schedule 05.04.2013    source источник


Ответы (1)


Первый пример работает не так, как вы себе представляли. Хотя и параметр x, и глобальная переменная a указывают на один и тот же список, при выполнении (set! x '(mutated)) вы просто устанавливаете x (локальный параметр процедуры) так, чтобы он указывал на другой список, а a остается неизменным. Другое дело, если бы вы написали это:

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

Теперь a мутируется внутри процедуры. Вторая и третья процедуры изменяют содержимое списка a, на которое также указывает x, поэтому изменение отражается "снаружи" после возврата из процедуры.

person Óscar López    schedule 05.04.2013
comment
Хорошо, но как тогда set-car! и set-cdr! могут мутировать a в x? - person ; 05.04.2013