Comment peut-on mettre une variable locale dans une fonction en lisp ?
Merci d'avance
Comment peut-on mettre une variable locale dans une fonction en lisp ?
Merci d'avance
Avec un let : http://www.cc.gatech.edu/classes/AY2...pTutorial.html
J'avais essayé avec ca,
mais le problème est que la variable locale créée avec un "let" est modifiée par les appels récursifs,
en gros c'est la même variable qui est utilisé par tous les appels récursifs...
Voilà le code...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 (defun minmax (plateau joueur joueur_evalue profondeur opt) (let ((result '(0 (0 0))) (copie nil) (liste_coups (liste_coups_possibles plateau joueur)) (opt_virt 0) (coup_a_jouer nil) (fils '(0 (0 0))) ) (cond ((or (null liste_coups) (equal profondeur 0)) (setf (car result) (evaluation plateau joueur_evalue)) ;(print plateau) (print joueur) (print joueur_evalue) (print profondeur) (print opt) ) (t (cond ((equal opt 1) (setf (car result) -100000) (dolist (coup_a_jouer liste_coups) ;(print plateau) (setf copie '((0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0))) (copie_plateau plateau copie) (update copie coup_a_jouer joueur);(print copie) (print plateau)(print " ") (setf fils (minmax copie (- 3 joueur) joueur_evalue (- profondeur 1) (- 1 opt))) (cond ((> (car fils) (car result)) (setf (car result) (car fils)) (setf (cadr result) coup_a_jouer))) ) ) ((equal opt 0) (setf (car result) 100000) (dolist (coup_a_jouer liste_coups);(print plateau) (setf copie '((0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0))) (copie_plateau plateau copie);(print copie)(print plateau) (update copie coup_a_jouer joueur);(print copie)(print plateau)(print " ") (setf fils (minmax copie (- 3 joueur) joueur_evalue (- profondeur 1) (- 1 opt))) (cond ((< (car fils) (car result)) (setf (car result) (car fils)) (setf (cadr result) coup_a_jouer))) ) ) ) ) ) result ))
L'appel récursif modifie la variable locale "result"...
Il faut appuyer sur le bouton # de l'éditeur pour avoir les balises [CODE]
"La haine seule fait des choix" - Koan Zen
"Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
"Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
Faites du Prolog, ça vous changera les idées !
Ma page Prolog
Mes codes sources commentés
Mon avatar : La Madeleine à la veilleuse de Georges de La Tour
Bonjour,
1. je ne sais pas si tu _veux_ comprendre ce que tu as fait...
Supposons que ce soit le cas.
Il se trouve que tu as construit (bien involontairement, je suppose) ce qu'on appelle une "closure".
En voici un exemple très simple:
Ca ressemble énormément à une variable globale (quoique pas accessible globalement) et ça ressemble encore plus à ce qu'on appelle une variable locale statique (dans d'autres langages (comme C)).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 (defun foo (x) (let ((closevar '(0))) (setf (car closevar) (+ (car closevar) x)) (car closevar))) ? (foo 0) => 0 ? (foo 1) => 1 ? (foo 0) => 1 ? (foo 1) => 2 ? (foo 0) => 2
En fait, le bout de code avec le "setf" modifie physiquement la donnée " '(0) " (qui est un cons dont le car est 0, AVANT TOUT APPEL DE LA FONCTION, et dont le cdr est NIL) qui est incluse dans le code de la fonction.
Ce qui revient à dire que le code se modifie lui-même!
(tu peux le vérifier en pretty-printant le code de la fonction (avec ^P en Le_Lisp))
Si tu compiles la fonction en Le_Lisp et que tu regardes la plist du symbole foo, tu verras où la donnée encapsulée est conservée à la compilation.
2. Pour résoudre à moindres frais ton problème, il suffit juste (mais ce n'est certainement pas la meilleure solution!!! (et j'avoue que je n'ai pas essayé de comprendre ton code (ni, bien sûr, de vérifier si ma solution marche vraiment (mais j'ai plutôt bon espoir...)))) que tu mettes un "copy" devant _toutes_ les données incluses dans ton code.
Par exemple:
3. Evidemment, tu peux aussi envosager d'écrire ton code différemment, comme le suggère justement Garulfo.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 (defun minmax (plateau joueur joueur_evalue profondeur opt) (let ((result (copy '(0 (0 0)))) ... (setf copie (copy '((0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)(0 0 0 0 0 0 0 0)))) ...
4. Personnellement, je le réécrirais en objet (en CLOS ou Smeci, par exemple), en tentant d'être clair sur les objets manipulés (plateau, joueur, coup, resultat, etc.).
HTH
)jack(
Partager