下面的代码将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
绑定(bind)到文字表达式'(stuff nil)
。该函数破坏性地更改z
,从而破坏性地更改文字的值。在这种情况下,LISP的行为方式取决于实现。一些实现会乖乖地更改文字值(如您的情况)。其他实现将文字放在只读存储器位置,如果您尝试修改这些文字,将会失败。
要获得所需的行为,请使用COPY-LIST
制作可以安全修改的文字副本:
(defun foo (m)
(let ((z (copy-list '(stuff nil))))
(push m (getf z 'stuff))
(print z)))
关于lisp - Common Lisp中的属性列表是否引用某些全局状态?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4632461/