Единственное, что вам нужно, это неизменяемые объекты и только обновлять привязки. setq
(и setf
с символом в качестве первого аргумента) делает это отлично. Вот несколько примеров:
(defparameter *test* '(1 2))
(defparameter *test2* *test*) ; a copy
(setf *test* (cdr *test*)) ; *test* is (2), but *test2* is still (1 2)
(defparameter *test3* *test*) ; a new copy
(setf *test* (cons 3 *test*)) ; *test* is (3 2), but *test2* is still (1 2) and *test3* is still (2)
push
и pop
делает это для вас. Вот тот же код:
(defparameter *test* '(1 2))
(defparameter *test2* *test*) ; a copy
(pop *test*) ; *test* is (2), but *test2* is still (1 2)
(defparameter *test3* *test*) ; a new copy
(push 3 *test*) ; (3 2), but *test2* is still (1 2) and *test3* is still (2)
Здесь я не делаю (setf (car *test*) 3)
, поскольку он мутирует объект, и все ссылки получат один и тот же объект, поскольку они указывают на объект, который я изменил.
Так что, если у вас есть какое-то более сложное состояние, такое как хеш-таблица, вам нужно будет превратить его в дерево, чтобы вы могли изменять log (n) узлов для каждого обновления, и оно будет работать таким же образом , что старые ссылки все еще имеют то же состояние.