5

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

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

4

1 回答 1

6

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

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

(defun foo (m)
  (let ((z (copy-list '(stuff nil))))
    (push m (getf z 'stuff))
    (print z)))
于 2011-01-08T05:39:01.623 回答