下面的代码将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/

10-15 08:26