Lisp 设置全局变量将还原为最后一个值

Lisp 设置全局变量将还原为最后一个值,lisp,common-lisp,Lisp,Common Lisp,当我试图在一个方法中设置一个全局参数时,我得到了一些奇怪的行为 (defparameter *global-var-1* nil) (defun method1 () (setf *global-var-1* '()) (format t "~a~%" *global-var-1*) ... (loop ... (setf *global-var-1* '(a)) (format t "~a~%" *global-var-1*)

当我试图在一个方法中设置一个全局参数时,我得到了一些奇怪的行为

(defparameter *global-var-1* nil)

(defun method1 ()
   (setf *global-var-1* '())
   (format t "~a~%" *global-var-1*)

   ...
   (loop
      ...

      (setf *global-var-1* '(a))
      (format t "~a~%" *global-var-1*)

      (nconc *global-var-1* (list '(b c))))

在上面的代码中,当我调用method1时,第一个format语句总是按预期打印
nil
。第二个format语句在第一次调用method1时打印
(A)
,但在第二次打印
(A(B C))
。第三次
(A(B C)(B C))
等等。setf似乎没有将
*global-var-1*
设置为
(A)
,而是将其设置为以前的已知值。我做错了什么?顺便说一句,我将
*global-var-1
设置为
(A)
,因为
ncoc
无法处理空列表。在退出方法1之前,我稍后会删除
(A)

当然
ncoc
可以处理空列表,但您必须始终指定其返回值,如下所示:

CL-USER> (defparameter *x* nil)
*X*
CL-USER> (setq *x* (nconc *x* (list 'a)))
(A)
CL-USER> *x*
(A)
然后,通过不使用文字列表解决您的问题:

CL-USER> (defparameter *x* nil)
*X*
CL-USER> (defun foo ()
           (setf *x* nil)
           (dotimes (n 3)
             (progn (setf *x* (list 'a))
                    (format t "~a~%" *x*)
                    (setf *x* (nconc *x* (list (list 'b 'c)))))))
FOO
CL-USER> (foo)
(A)
(A)
(A)
在使用破坏性操作时,应始终小心,并注意将其与文字表达式一起使用的含义。在您的代码中,
ncoc
破坏性地修改了
'(a)
列表文字的
cdr
,从而导致您观察到的行为。(如果不进行优化,可以使用
append
来解决此问题。)

您可能也对我关于这个主题的介绍感兴趣。

谢谢。我在使用append,我想让代码更快一点,因此使用了ncoc。对于lisp来说还是个新手,我总是忘记,在c或java中看起来像文字的东西在lisp中是一个符号,具有这样的后果。