2012-03-17 60 views
0

即使(我相信)我只在每個函數中使用局部變量,多次運行後的結果看起來像數據保留在變量中,它最終會添加舊的&新的結果。哪裏不對?本地變量保留以前執行的數據

(defun funcC (target res) 
    (cond 
    ((null res) (list (list target 1))) 
    ((equal (car (car res)) target) 
    (setf (cadr (car res)) (+ (cadr (car res)) 1)) 
    res) 
    (t (setf (cdr res) (funcC target (cdr res))) res) 
)) 
(defun funcB (l res) 
    (cond ((null l) nil) 
    ((atom l) (funcC l res)) 
    ((atom (car l)) 
    (funcB (car l) res) 
    (funcB (cdr l) res)) 
    ((listp (car l)) (funcB (car l) res)) 
    (t (funcB (cdr l) res))) 
    res 
) 
(defun funcA (l) 
    (cdr (funcB l '(()))) 
) 

結果:

Break 27 [30]> lb 
(10 7 7 7 4 3 7 3 10 10) 
Break 27 [30]> (funcA lb) 
((10 3) (7 4) (4 1) (3 2)) ; I want this result to repeat in the next run but... 
Break 27 [30]> (funcA lb) 
((10 6) (7 8) (4 2) (3 4)) 
Break 27 [30]> (funcA lb) 
((10 9) (7 12) (4 3) (3 6)) ; Each run adds up to results from previous run 

環境:Ubuntu的11.10,GNU CLISP 2.49

回答

3

這是一個經常被問到的問題。在stackoverflow上應該有這個問題的副本(原文!)。

您的funcA包含文字數據。這些數據每次都會傳到funcB並在那裏修改。

您應該爲每次運行製作一份新數據。使用COPY-TREE

請注意,根據Common Lisp標準,修改文字數據可能會導致未定義的後果。想象一下,例如一個編譯器,它將所有文字數據放在只讀數據存儲器段中,或想象一個編譯器在幾個地方重複使用類似的文字數據以節省空間。

+1

難道我們也可以用'(list(list))'來代替''(())'嗎? – lindes 2012-03-17 18:32:50

+1

@lindes:是的。任何剛剛混淆的數據都可以。 – 2012-03-17 19:09:34