Common Lisp中的属性列表是否引用了某些全局状态?

Common Lisp中的属性列表是否引用了某些全局状态?,lisp,common-lisp,sbcl,Lisp,Common Lisp,Sbcl,下面的代码将z作为一个局部变量,但其行为就像是一个全局变量: (defun foo (m) (let ((z '(stuff nil))) (push m (getf z 'stuff)) (print z))) (foo 1) (foo 2) (foo 3) 我希望输出是 (STUFF (1)) (STUFF (2)) (STUFF (3)) T 但是当用SBCL运行它时,我明白了 (STUFF (1)) (STUFF (2 1)) (STUFF (3 2

下面的代码将
z
作为一个局部变量,但其行为就像是一个全局变量:

(defun foo (m)
  (let ((z '(stuff nil)))
    (push m (getf z 'stuff))
    (print z)))

(foo 1)
(foo 2)
(foo 3)
我希望输出是

(STUFF (1)) 
(STUFF (2)) 
(STUFF (3)) 
T
但是当用SBCL运行它时,我明白了

(STUFF (1)) 
(STUFF (2 1)) 
(STUFF (3 2 1)) 
T

为什么会这样?这种行为是属性列表特有的吗?

foo
中,
z
绑定到文本表达式
'(stuff nil)
。函数以破坏性方式更改
z
,从而破坏性地更改文本的值。LISP在这种情况下的行为取决于实现。一些实现将顺从地更改文本值(如您的情况)。其他实现将文本放在只读内存位置,如果尝试修改这些文本,则将失败

要获得所需的行为,请使用
COPY-LIST
复制可以安全修改的文本:

(defun foo (m)
  (let ((z (copy-list '(stuff nil))))
    (push m (getf z 'stuff))
    (print z)))

我认为更惯用的方法是使用
LIST
,如
(let((z(LIST'stuff nil))…)
可能重复的