2011-11-07 64 views
2

當我嘗試在方法中設置全局參數時,出現了一些奇怪的行爲。設置全局變量恢復爲上一個值

(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)))) 

在上面的代碼,當我打電話方法1,第一格式語句始終打印nil預期。第二次格式聲明在第一次調用方法1時打印(A),但第二次打印(A (B C))。第三次(A (B C) (B C))等。而不是將*global-var-1*設置爲(A),setf似乎將其設置爲先前已知的值。我究竟做錯了什麼?順便說一下,我設置*global-var-1(A),因爲nconc將無法​​使用空列表。稍後在退出方法1之前刪除(A)

回答

6

當然nconc作品以空列表,但是你必須始終指定它的返回值,就像這樣:

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) 

CL-USER> (defparameter *x* nil) 
*X* 
CL-USER> (setq *x* (nconc *x* (list 'a))) 
(A) 
CL-USER> *x* 
(A) 

然後,你的問題是由不使用文字列表解決在使用破壞性操作時,您應該小心謹慎,並注意將它們與字面表達式結合使用的含義。在您的代碼中,nconc破壞性地修改了您的'(a)列表文字的cdr,這會導致您觀察到的行爲。 (如果你沒有優化,你總是可以使用append來解決這個問題。)

你可能也對我的other answer有興趣關於這個話題。

+0

謝謝。我正在使用** append **,我想讓代碼更快一些,因此** nconc **。還是新的lisp,我一直忘記,看起來像c或java中的文字是Lisp中的符號,並帶有這樣的後果。 – WanderingPhd