Discussion:
Variables globales / Passage de paramètres
(trop ancien pour répondre)
lionmarron
2011-12-21 21:39:16 UTC
Permalink
Bonjour

Étant presque sûr de ne pas faire comme il faut, et non moins sûr de ne
pas savoir comment il faudrait faire, je me propose de choisir un
exemple précis pour expliquer non pas comment je fais en général, mais
comment j'ai fait cette fois.

Espérant qu'en retour, au lieu de m'expliquer pourquoi j'ai tord en
général (mais je n'en doute pas), on pourra m'expliquer aussi pourquoi
j'ai eu tord cette fois là (puisque tel est sans doute le cas).


CONTEXTE

Les réponses aux questions qui pourront se poser varient selon les
langages. C'est une chose que j'imagine ou dont je suis sûr (selon les cas).

Toutefois je préférais partir d'un exemple précis, donc le programme est
en Python, même si cela ne m'a pas semblé une raison suffisante pour
mettre le message sur le forum python.

D'une part les questions posées doivent être a priori suffisamment
basiques pour être assez peu spécifique à ce langage. D'autre part il
pourrait arriver que des réponses relatives à d'autres langages soient
plus appropriées.

Le programme choisi comme exemple ne sert pas vraiment à quelque chose,
toutefois ce qu'il fait est non ambigu (on peut savoir assez facilement
si l'objectif est atteint ou non), et cela devrait être a priori
suffisamment compliqué pour qu'on puisse hésiter sur la façon de
procéder, ou pour que le résultat puisse être obtenu par des méthodes
plus ou moins claires.

Ce que fait le programme: dessiner des pièces d'échecs, permettre de les
déplacer, contrôler la légalité des coups. On ne peut pas enregistrer ce
qu'on vient de faire dans un fichier, ni conserver en mémoires des
variantes, mais on peut retourner en arrière ou revenir en avant.

Le script ne présente sans doute pas un grand intérêt et je ne crois pas
qu'il soit nécessaire de le voir pour comprendre la suite du message,
toutefois on peut le trouver ici :

https://sites.google.com/site/andrehetzel/5-programmation/b-python

J'ai cru devoir séparer le script en deux parties, disons A et B, la
seconde appelant la première.

A contrôle la légalité des coups. B dessine les pièces, puis gère leur
déplaceent. Donc la question qui s'est posée, celle qui sera posée ici
tout au moins : comment passer les paramètres ?

Les paramètres gérées par B et utilisés par A sont essentiellement deux
listes de 24 nombres. Elles font partie de deux listes de listes
appelées respectivement posiCNT et posiCT (position de la couleur qui
n'est pas au trait / position de la couleur au trait).

Les paramètres calculés par A et utilisés par B sont essentiellement: --
Une liste appelée depCL (départ coups légaux) ; elle contient 64 nombres
qui peuvent prendre les valeurs 0 ou 1.
-- Une liste appelée arrCL (arrivée coups légaux) ; elle contient 64
listes de 64 nombres qui peuvent prendre les valeurs 0 ou 1.


COMMENT J'AI FAIT ?

Uniquement avec des variables globales.

Dans le premier cas (appel de A), mettre en paramètre les deux listes de
24 nombres n'aurait pas posé de problèmes. Seulement voilà, cela
n'aurait pas non plus changé grand chose : parce que la fonction A
utilise une dizaine de listes de 64 à 123 nombres qui n'ont besoin
d'être initialisées qu'une fois, et dont j'ai fait des variables
globales afin qu'elles ne soient pas réinitialisées à chaque appel de A.

Dans le second cas (retour de A) il y aurait sans doute eu des moyens de
récupérer les paramètres, mais il est déjà moins évident de savoir quels
sont ces moyens. Il est bien possible que le seul que je connaisse
aurait fonctionné (mettre qq chose après return) mais je ne sais pas
s'il aurait été le plus simple. Et là aussi cela semblait ne pas changer
grand chose.


CARACTÉRISTIQUE DU LANGAGE OU DE L'ÉDITEUR

J'ai d'abord essayé de mettre A dans un module séparé mais je n'y suis
pas arrivé, soit parce que je ne sais pas utiliser mon éditeur (ce
serait un autre sujet si j'étais sûr que le problème vienne de là | donc
peut-être pas), soit parce que le principal livre auquel je me suis
référé (Swinnen, O'Reilly 2005) explique seulement comment utiliser des
modules déjà réalisés, ou comment réaliser des modules qui puissent
fonctionner seuls, mais pas comment réaliser un module en le testant
depuis un autre script.

Lorsque le module venait d'être modifié, selon les cas et selon la façon
de procéder, le lancement du script appelant provoquait soit un message
d'erreur, soit l'appel de la version précédente du script, soit encore
un fonctionnement correct (mais en général c'était après avoir fermé
puis réouvert tous les fichiers).

Que cela provienne de l'éditeur ou non, le fonctionnement de Python
semble de toute façon parfois bizarre.

Lorsqu'on lance un script venant d'être modifié (et sauf si on prend la
précaution de fermer puis réouvrir le script), Python continu de faire
comme si des variables ou des fonctions qui ne sont plus déclarées
existaient encore pour lui. Et je ne pense pas que cela vienne de
l'éditeur que j'utilise en ce moment (Emacs) ; j'avais remarqué la même
choses sous IDLE.


LE MEILLEUR DES MONDES

Dans certains cas le fait que les langages de programmation semblent ne
pas proposer ce que je cherche doit s'expliquer par le fait que je ne
sais pas précisément ce qu'ils proposent. Il serait par exemple
surprenant qu'il ne soit pas possible d'initialiser certaines variables
locales seulement lors du premier appel d'une fonction. Ce qu'on appelle
variables statiques permettrait de le faire et la première fois que j'en
ai entendu parler il me semble que c'était à propos de Python. Toutefois
je n'ai pas pu retrouver l'information, et je ne sais pas pourquoi les
ouvrages d'initiation n'en parlent pas alors qu'ils parlent de choses
plus difficile à comprendre.

Dans d'autres cas ce que cherche semble suffisamment différent de ce
dont on entend parler pour que je puisse penser que ça n'existe pas sur
le marcher actuel. Comme par ailleurs mes idées sont relativement
simples ou relativement triviales, je peux raisonnablement penser que ce
qu'on me propose doit être beaucoup mieux.

Autrement dit le meilleur des mondes peut-être ; ce que je peux en dire
est seulement que je n'y vois pas de certitude. Difficile d'être plus
affirmatif si ce qu'on me propose est incompréhensible.

Quant à savoir ce que je cherche, je citerai seulement deux idées et
sans les développer ; d'une part parce que je crois que mon message sera
suffisamment long comme ça ; d'autre part parce que je suppose qu'il
aurait été jugé suffisamment navrant même sans ça.

Première idée : Il devrait y avoir plusieurs niveaux de numéros de
lignes ; c'est-à-dire que, dans le cas de l'écriture d'une fonction, le
rôle joué en Python par l'augmentation de la marge droite devrait être
remplacé par une colonne supplémentaire de numéros de lignes. Cela
obligerait à faire en sorte que les numéros de lignes fasse partie du
script mais ce n'est pas la seule différence. En réalité cela s'inscrit
dans le cadre d'une conception différente de l'éditeur, et, bien que (je
suppose) jusque là un éditeur pourrait être programmé pour le faire, en
réalité ce qu'il s'agit de faire devrait plutôt être réalisé par un
programme qui serve à la fois d'éditeur et d'interpréteur. Je n'explique
pas plus les avantages pour ne pas être trop long mais évidemment il ne
s'agit pas de revenir à GWbasic. Si j'ai choisi cet exemple c'est parce
qu'il est suffisant pour qu'on puisse savoir ou non si un langage
proposant cette possibilité existe actuellement (mais je crois pas).

Deuxième idée : Il devrait exister deux type de scripts. Un type qui
correspond à ce que fait aujourd'hui un script normal ; nous
l'appellerons alpha. Et type qui serve à débugger un script du type
précédent ; nous l'appellerons delta. Alpha et delta fonctionneraient en
même temps, et delta contiendrait des instructions servant à contrôler
ce que fait alpha. Par exemple indiquer quelles sont les valeurs
successives d'une variable dans une zone déterminé du programme, ou à un
moment déterminé de son déroulement. Ce serait bien sûr plus facile à
faire (ou plus adapté) avec un langage interprété qu'avec un langage
compilé, et a priori l'idée ne devrait pas être assez originale pour
qu'elle n'ait pas déjà été utilisée (j'ai lu au moins une fois qq chose
qui irait dans ce sens), mais je ne sais pas si on la trouve implémenté
sur un langage actuel.


FIN DU MESSAGE

Et j'ignore encore si ce sera un troll bien sûr.
--
lionmarron
Pascal J. Bourguignon
2011-12-21 23:16:53 UTC
Permalink
Post by lionmarron
Ce que fait le programme: dessiner des pièces d'échecs, permettre de
les déplacer, contrôler la légalité des coups. On ne peut pas
enregistrer ce qu'on vient de faire dans un fichier, ni conserver en
mémoires des variantes, mais on peut retourner en arrière ou revenir
en avant.
[...]
A contrôle la légalité des coups. B dessine les pièces, puis gère leur
déplaceent. Donc la question qui s'est posée, celle qui sera posée ici
tout au moins : comment passer les paramètres ?
Les paramètres gérées par B et utilisés par A sont essentiellement
deux listes de 24 nombres. Elles font partie de deux listes de listes
appelées respectivement posiCNT et posiCT (position de la couleur qui
n'est pas au trait / position de la couleur au trait).
Non.

Le programme traite de pièces d'échecs, d'un échéquier, du movement des
pièces, du contrôle de la légalité des coups. Pas de liste de nombres.

Les paramètres gérés doivent être des échéquiers, des pièces d'échec,
des movement de pièce d'échec. Les nombres et les listes n'ont rien à
faire la dedans.
Post by lionmarron
Les paramètres calculés par A et utilisés par B sont essentiellement: --
Une liste appelée depCL (départ coups légaux) ; elle contient 64
nombres qui peuvent prendre les valeurs 0 ou 1.
-- Une liste appelée arrCL (arrivée coups légaux) ; elle contient 64
listes de 64 nombres qui peuvent prendre les valeurs 0 ou 1.
C'est n'importe quoi. Ça n'a aucun rapport avec les échecs.
D'autre part, cette modélisation des movements légaux est ridicule (elle
prend trop de place).
Post by lionmarron
Uniquement avec des variables globales.
Non. L'utilisation inconsidérée de variables globales mène à des
interdépendences inconsidérées entre les modules.
Post by lionmarron
Dans certains cas le fait que les langages de programmation semblent
ne pas proposer ce que je cherche doit s'expliquer par le fait que je
ne sais pas précisément ce qu'ils proposent.
En effet, c'est difficile de programmer quand on ne connait pas son
langage de programmation. Plus d'étude et de pratique sont nécessaire.
Mais les questions sur les langages de programmations doivent être
posées dans les groupes concernés.
Post by lionmarron
Quant à savoir ce que je cherche, je citerai seulement deux idées et
sans les développer ; d'une part parce que je crois que mon message
sera suffisamment long comme ça ; d'autre part parce que je suppose
qu'il aurait été jugé suffisamment navrant même sans ça.
Ah! Le plaisir du clavier!
Post by lionmarron
Première idée : Il devrait y avoir plusieurs niveaux de numéros de
lignes ; c'est-à-dire que, dans le cas de l'écriture d'une fonction,
le rôle joué en Python par l'augmentation de la marge droite devrait
être remplacé par une colonne supplémentaire de numéros de
lignes. Cela obligerait à faire en sorte que les numéros de lignes
fasse partie du script mais ce n'est pas la seule différence. En
réalité cela s'inscrit dans le cadre d'une conception différente de
l'éditeur, et, bien que (je suppose) jusque là un éditeur pourrait
être programmé pour le faire, en réalité ce qu'il s'agit de faire
devrait plutôt être réalisé par un programme qui serve à la fois
d'éditeur et d'interpréteur. Je n'explique pas plus les avantages pour
ne pas être trop long mais évidemment il ne s'agit pas de revenir à
GWbasic. Si j'ai choisi cet exemple c'est parce qu'il est suffisant
pour qu'on puisse savoir ou non si un langage proposant cette
possibilité existe actuellement (mais je crois pas).
Je ne sais pas quel intérêt celà aurait, mais il est tout à fait
possible de programmer emacs (voir ci-dessous), pour ajouter ces
fonctionalités. En particulier dans les modes pour des langage de
programmation utilisant des numéros de lignes, ceux-ci sont ajoutés
automatiquement. Voir par exemple la commande lse-newline dans
lse-mode.el: http://paste.lisp.org/display/124689

Il est aussi possible d'écrire en emacs lisp des filtres pour décorer un
source à son chargement pour l'éditer, et enlever les décorations lors
de l'enregistrement.
Post by lionmarron
Deuxième idée : Il devrait exister deux type de scripts. Un type qui
correspond à ce que fait aujourd'hui un script normal ; nous
l'appellerons alpha. Et type qui serve à débugger un script du type
précédent ; nous l'appellerons delta. Alpha et delta fonctionneraient
en même temps, et delta contiendrait des instructions servant à
contrôler ce que fait alpha. Par exemple indiquer quelles sont les
valeurs successives d'une variable dans une zone déterminé du
programme, ou à un moment déterminé de son déroulement. Ce serait bien
sûr plus facile à faire (ou plus adapté) avec un langage interprété
qu'avec un langage compilé, et a priori l'idée ne devrait pas être
assez originale pour qu'elle n'ait pas déjà été utilisée (j'ai lu au
moins une fois qq chose qui irait dans ce sens), mais je ne sais pas
si on la trouve implémenté sur un langage actuel.
C'est le cas. Avec emacs, alpha est le langage de programmation utilisé
pour écrire ton programme, delta est emacs lisp, le langage de
programmation d'emacs, avec lequel tu peux écrire des scripts pour
contrôler l'écriture de ton programme, ou son débogage. Un exemple
frappant est slime http://common-lisp.net/project/slime/ (dans le cas de
slime, alpha est Common Lisp). slime est architecturé en deux modules,
l'un écrit en emacs lisp (delta) nommé slime, et l'autre écrit en Common
Lisp (alpha) nommé swank. Ces deux modules communiquent afin de
contrôler la compilation, le chargement, l'évaluation et le déboguage
des programmes écrits en Common Lisp à partir d'emacs.

Bien entendu, les divers modes qui permettent l'exécution des différents
langages à partir d'emacs fonctionnent plus ou moins de la même manière.
Il ne te reste plus qu'à écrire en delta, je veux dire, en emacs lisp,
les fonctions supplémentaires dont tu as besoin pour déboguer tes
programmes en alpha, je veux dire, en python, peut être en s'inspirant
de slime. Certains on écrit des modules swank pour différents langages
de programmations (je sais qu'il en existe pour scheme et R, peut être
pour d'autres).
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
lionmarron
2011-12-22 14:16:48 UTC
Permalink
Post by Pascal J. Bourguignon
[...]
Post by lionmarron
A contrôle la légalité des coups. B dessine les pièces, puis gère leur
déplaceent. Donc la question qui s'est posée, celle qui sera posée ici
tout au moins : comment passer les paramètres ?
Les paramètres gérées par B et utilisés par A sont essentiellement
deux listes de 24 nombres. Elles font partie de deux listes de listes
appelées respectivement posiCNT et posiCT (position de la couleur qui
n'est pas au trait / position de la couleur au trait).
Non.
Le programme traite de pièces d'échecs, d'un échéquier, du movement des
pièces, du contrôle de la légalité des coups. Pas de liste de nombres.
Les paramètres gérés doivent être des échéquiers, des pièces d'échec,
des movement de pièce d'échec. Les nombres et les listes n'ont rien à
faire la dedans.
Commençons par parler français alors. Il s'agit de dire quelles
informations provenant de B sont utilisées par A, et de quelle façon
elles sont transmises. Si ces informations sont transmises par des
nombres, même en toute rigueur, et surtout dans le contexte, je ne vois
pas pourquoi on devrait dire qu'elles ne sont pas des nombres.
Post by Pascal J. Bourguignon
Post by lionmarron
Les paramètres calculés par A et utilisés par B sont essentiellement: --
Une liste appelée depCL (départ coups légaux) ; elle contient 64
nombres qui peuvent prendre les valeurs 0 ou 1.
-- Une liste appelée arrCL (arrivée coups légaux) ; elle contient 64
listes de 64 nombres qui peuvent prendre les valeurs 0 ou 1.
C'est n'importe quoi. Ça n'a aucun rapport avec les échecs.
Je débute m'sieur.
Post by Pascal J. Bourguignon
D'autre part, cette modélisation
À l'intention de ceux pour lesquels le français est une langue d'usage
courant (ce qui est visiblement votre cas), là où vous mettez
modélisation il me semble que le terme précis serait plutôt représentation.
Post by Pascal J. Bourguignon
des movements légaux est ridicule (elle
prend trop de place).
Même si le programme était complété de fonctions nouvelles, il n'y
aurait pas de raisons pour que les informations ainsi représentées
soient enregistrées sur le disque dur. (Contrairement aux informations
sur les déplacements successifs par exemple.) Dans ces conditions je
n'ai pas cru que ce paramètre présente un caractère critique.
Post by Pascal J. Bourguignon
Post by lionmarron
Deuxième idée : Il devrait exister deux type de scripts. Un type qui
correspond à ce que fait aujourd'hui un script normal ; nous
l'appellerons alpha. Et type qui serve à débugger un script du type
précédent ; nous l'appellerons delta. Alpha et delta fonctionneraient
en même temps, et delta contiendrait des instructions servant à
contrôler ce que fait alpha. Par exemple indiquer quelles sont les
valeurs successives d'une variable dans une zone déterminé du
programme, ou à un moment déterminé de son déroulement. Ce serait bien
sûr plus facile à faire (ou plus adapté) avec un langage interprété
qu'avec un langage compilé, et a priori l'idée ne devrait pas être
assez originale pour qu'elle n'ait pas déjà été utilisée (j'ai lu au
moins une fois qq chose qui irait dans ce sens), mais je ne sais pas
si on la trouve implémenté sur un langage actuel.
C'est le cas. Avec emacs, alpha est le langage de programmation utilisé
pour écrire ton programme, delta est emacs lisp, le langage de
programmation d'emacs, avec lequel tu peux écrire des scripts pour
contrôler l'écriture de ton programme, ou son débogage. Un exemple
frappant est slime http://common-lisp.net/project/slime/ (dans le cas de
slime, alpha est Common Lisp). slime est architecturé en deux modules,
l'un écrit en emacs lisp (delta) nommé slime, et l'autre écrit en Common
Lisp (alpha) nommé swank. Ces deux modules communiquent afin de
contrôler la compilation, le chargement, l'évaluation et le déboguage
des programmes écrits en Common Lisp à partir d'emacs.
Bien entendu, les divers modes qui permettent l'exécution des différents
langages à partir d'emacs fonctionnent plus ou moins de la même manière.
Il ne te reste plus qu'à écrire en delta, je veux dire, en emacs lisp,
les fonctions supplémentaires dont tu as besoin pour déboguer tes
programmes en alpha, je veux dire, en python, peut être en s'inspirant
de slime. Certains on écrit des modules swank pour différents langages
de programmations (je sais qu'il en existe pour scheme et R, peut être
pour d'autres).
Merci pour ces infos.
--
lionmarron
Pascal J. Bourguignon
2011-12-22 14:29:14 UTC
Permalink
Post by lionmarron
Post by Pascal J. Bourguignon
[...]
Post by lionmarron
A contrôle la légalité des coups. B dessine les pièces, puis gère leur
déplaceent. Donc la question qui s'est posée, celle qui sera posée ici
tout au moins : comment passer les paramètres ?
Les paramètres gérées par B et utilisés par A sont essentiellement
deux listes de 24 nombres. Elles font partie de deux listes de listes
appelées respectivement posiCNT et posiCT (position de la couleur qui
n'est pas au trait / position de la couleur au trait).
Non.
Le programme traite de pièces d'échecs, d'un échéquier, du movement des
pièces, du contrôle de la légalité des coups. Pas de liste de nombres.
Les paramètres gérés doivent être des échéquiers, des pièces d'échec,
des movement de pièce d'échec. Les nombres et les listes n'ont rien à
faire la dedans.
Commençons par parler français alors. Il s'agit de dire quelles
informations provenant de B sont utilisées par A, et de quelle façon
elles sont transmises. Si ces informations sont transmises par des
nombres, même en toute rigueur, et surtout dans le contexte, je ne
vois pas pourquoi on devrait dire qu'elles ne sont pas des nombres.
Parce qu'un des principes de bonne programmation c'est d'utiliser des
abstractions au bon niveau.

Si tu veux parler de nombres au lieu de pièces d'échec, pourquoi ne pas
parler aussi d'atomes ou de quartz?

Dans les ordinateurs actuels, il n'y a pas de nombre. Il y a des charges
électriques et des niveaux quantiques. Alors en toutes rigueur, il
faudrait parler de ça?



Non. Quand on a un problème de jeu d'échec, on parle de jeu d'échec.
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
lionmarron
2011-12-22 15:19:15 UTC
Permalink
Post by Pascal J. Bourguignon
[...]
Post by lionmarron
elles sont transmises. Si ces informations sont transmises par des
nombres, même en toute rigueur, et surtout dans le contexte, je ne
vois pas pourquoi on devrait dire qu'elles ne sont pas des nombres.
Parce qu'un des principes de bonne programmation c'est d'utiliser des
abstractions au bon niveau.
Il faudra que je continue de prendre des cours alors.
--
lionmarron
Loading...