我想知道如何在Common Lisp中执行以下操作。假设我在内存中有一个在特定时间唯一的对象(实体)。我想做的是将某个变量设置为该对象的状态,作为特定时间的快照。然后原始实体可能会进化。但是,我想确保该变量过去仍指向该实体的状态。
看来,我需要的是深复制+ setter的内容。复杂的因素是,实体的性质有时是未知的。它可以是数组,也可以是哈希表。它可能同样是一个对象。
任何建议都值得赞赏。
答案 0 :(得分:3)
您唯一需要的是不可变对象,并且仅更新绑定。 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)个节点,并且它将以相同的方式工作,则旧的引用仍具有相同的状态。