当我尝试在方法中设置全局参数时,我会遇到一些奇怪的行为.
(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))))
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,当我调用method1时,第一个格式语句总是nil按预期打印.第二个格式语句打印(A)第一次调用method1,但第二次打印(A (B C)).第三次(A (B C) (B C))等等.setf似乎将其设置为先前的已知值,而不是设置*global-var-1*为(A).我究竟做错了什么?顺便说一下,我正在设置*global-var-1,(A)因为nconc无法使用空列表.我(A)在退出method1之前删除.
当然nconc可以使用空列表,但必须始终指定其返回值,如下所示:
CL-USER> (defparameter *x* nil)
*X*
CL-USER> (setq *x* (nconc *x* (list 'a)))
(A)
CL-USER> *x*
(A)
Run Code Online (Sandbox Code Playgroud)
然后,通过不使用文字列表解决您的问题:
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)
Run Code Online (Sandbox Code Playgroud)
在使用破坏性操作时应始终小心,并注意将它们与文字表达式一起使用的含义.在你的代码,nconc破坏性修改cdr您的'(a)列表的文本,这将导致你所观察到的行为.(append如果你没有进行优化,你总是可以用它来解决这个问题.)
您可能也对我关于此主题的其他答案感兴趣.