Схема: путаница с множеством! - PullRequest
2 голосов
/ 06 июня 2010

Я запутался, как работает этот код:

(define m (list 1 2 3 '(5 8)))
(let ((l (cdr m)))
(set! l '(28 88))) ==>(1 2 3 (5 8))

(define o (list 1 2 3 '(5 8)))
(let ((l (cdr o)))
(set-car! l '(28 88))) ==> (1 (28 88) 3 (5 8))

Почему (set! l '(28 88))) не обновляется m?

Ответы [ 4 ]

7 голосов
/ 06 июня 2010

установлен!не может изменить список (или любую другую структуру, в отличие от set-car / cdr!), но изменить только привязку (в вашем случае локальной l ) переменной.

(define x 3)
(define f (lambda (x) (set! x 4)))
(define g (lambda (y) (set! x y)))
(f x)
x 
-> 3
(g 5)
x
-> 5
1 голос
/ 09 июня 2010

set! только изменяет привязку символа, часто позволяя сборщику мусора использовать свое первоначальное значение. Он не изменяет данные, он связывает символ. Следовательно, такие вещи, как (set! (car '(symbol symbol2)) 3), не работают, даже если вторая подчиненная форма имеет значение символа.

Чтобы действительно изменять данные в памяти, необходимо использовать одну из форм set-car!, set-cdr!, set-vector! и так далее. Они имеют совершенно разную семантику и действительно оценивают свою вторую подформу, и любые данные, которые она оценивает, затем обновляются в памяти, изменяя значение всех других символов, которые совместно используют эту память.

1 голос
/ 06 июня 2010

Согласно ответу скептика, l была локальной переменной, и меняла ее через set! не собирается ничего делать м.

Если вы хотите, чтобы первое let вернуло ожидаемое значение, вам нужно продолжить, вернув новое значение локально связанного l, например, так:

(define m (list 1 2 3 '(5 8)))
(let ((l (cdr m)))
(set! l '(28 88))
  l)

(28 88)
0 голосов
/ 09 июня 2010

Речь идет не о мутировании, а о повторном связывании. И set!, и set-car! меняют указатели. В вашем примере l изначально указывает на cdr пары, которая также является парой. Когда вы set! l, вы говорите, чтобы он указывал на новое местоположение, которое содержит '(28 88).

Точно так же, когда вы делаете set-car!, вы говорите, что указатель car теперь будет указывать на местоположение B вместо его текущего местоположения A, но содержимое A не видоизменяется. Например:


(define list1 '(2 3)) 
(define list2 (list 72 list1 55))
(set-car! (cdr list2) 99)

list1 ==> '(2 3) 
list2 ==> '(72 99 55)
...