2012-03-17 1 views
0

avec le code ci-dessous, même si (je crois) j'utilise uniquement des variables locales dans chaque fonction, le résultat après plusieurs exécutions ressemble à des données qui restent dans des variables et finit par ajouter & nouveau résultat. Qu'est-ce qui ne va pas?La variable locale conserve les données de l'exécution précédente

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

Résultat:

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 

Environnement: Ubuntu 11.10, GNU CLISP 2,49

Répondre

3

C'est une question souvent posée. Il devrait y avoir des copies (sic!) De cette question sur stackoverflow.

Votre funcA contient des données littérales. Ces données sont transmises à chaque fois au funcB et modifiées ici.

Vous devriez faire une nouvelle copie de ces données pour chaque exécution. Utilisez COPY-TREE.

Notez également que la modification de données littérales peut avoir des conséquences indéfinies selon la norme Common Lisp. Imaginons par exemple un compilateur qui place toutes les données littérales dans des segments de mémoire de données en lecture seule ou imagine un compilateur qui réutilise des données littérales similaires à plusieurs endroits pour économiser de l'espace.

+1

Pourrait-on aussi faire quelque chose comme, disons '(liste (liste))', à la place de ''(())'? – lindes

+1

@lindes: oui. toute donnée fraîchement contrôlée fera l'affaire. –

Questions connexes