【问题标题】:Setting global variable reverts to last value设置全局变量恢复为最后一个值
【发布时间】:2011-11-07 23:18:18
【问题描述】:

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

(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时,第一个格式语句总是按预期打印nil。第二个格式语句在第一次调用 method1 时打印 (A),但第二次打印 (A (B C))。第三次(A (B C) (B C)) 以此类推。 setf 似乎没有将*global-var-1* 设置为(A),而是将其设置为以前的已知值。我究竟做错了什么?顺便说一句,我将*global-var-1 设置为(A),因为nconc 不适用于空列表。我稍后会在退出方法 1 之前删除 (A)

【问题讨论】:

    标签: lisp common-lisp


    【解决方案1】:

    当然nconc 可用于空列表,但您必须始终为其分配返回值,如下所示:

    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)
    

    在使用破坏性操作时应始终小心,并注意将它们与文字表达式一起使用的含义。在您的代码中,nconc 破坏性地修改了您的 '(a) 列表文字的 cdr,这导致了您观察到的行为。 (如果您不进行优化,您可以随时使用append 来解决这个问题。)

    你可能也对我的other answer关于这个话题感兴趣。

    【讨论】:

    • 谢谢。我使用的是append,我想让代码更快一点,因此使用了nconc。对 lisp 来说还是新手,我一直忘记在 c 或 java 中看起来像文字的东西在 lisp 中是一个符号,会产生这样的后果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 2020-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多