=head1 NOM namespaces - Les espaces de nom en Perl =head1 Les espaces de nom Au commencement, dans les années soixante, n'importe quelle partie de votre programme avait accès à n'importe quelle autre partie de votre programme. Il s'est avéré que c'était un problème. Alors les concepteurs de langages ont inventé les variables locales, lesquelles étaient seulement visibles dans une petite partie du programme. De cette façon, les programmeurs utilisant une variable C pouvaient être sûr que personne ne pouvait trifouiller son contenu dans leur dos. Ils pouvaient également être sûrs qu'en utilisant C ils ne trifouillaient pas la variable de quelqu'un d'autre par erreur. Tous les langages de programmation ont une philosophie et, de nos jours, la plupart de ces philosophies ont à voir avec la façon dont sont manipulés les noms de variables. Quelle variable est visible depuis quelle partie du programme, que veulent dire les noms, et S Voila des détails d'une importance cruciale. Ces détails vont du baroque, dans des langages comme Lisp, au vraiment très baroque dans des langages comme C++. Perl se classerait plutôt dans la catégorie rococo. Le problème avec Perl, ce n'est pas qu'il n'a pas de système de gestion des variables clairement défini mais plutôt qu'il a deux systèmes, tous deux à l'oeuvre en même temps. Il s'agit d'un grand secret à propos des variables Perl que beaucoup de gens apprennent trop S Perl a B jeux de variables complètement séparés et indépendants. L'un et hérité de Perl 4 et l'autre est nouveau. Les deux jeux de variables sont les «Evariables de packageE» et les «Evariables lexicalesE». Ils n'ont rien à voir entre eux. Les variables de package sont historiquement les premières alors nous commencerons par elles. Puis nous verrons quelques problèmes avec les variables de package, et comment les variables lexicales introduites avec Perl 5 viennent résoudre ces problèmes. Enfin nous verrons comment faire en sorte que Perl découvre automatiquement les endroit où il se pourrait que vous ne manipuliez pas la variable que vous croyez, ce qui permet de trouver les erreurs avant qu'elles ne deviennent des bugs. =head1 Les variables de package $x = 1 Ici, C est une variable de package. Il y a deux choses importantes à savoir à propos des variables de S Les variables de package, c'est ce que l'on obtient si on ne précise pas autre chose. Les variables de package sont B globales. B<«EGlobalE»> signifie que ces variables de package sont toujours visibles partout, dans tous les programmes. Une fois que vous avez fait C<$x = 1>, n'importe quelle partie du programme, même un sous-programme défini dans un autre fichier, peut inspecter et modifier la valeur de C<$x>. Il n'y a pas d'exception à cela; les variables de package sont toujours globales. Les variables de package sont divisées en familles appelées B. Toutes les variables de package ont un nom en deux parties. Ces deux parties sont un peu comme le nom de famille et le prénom des variables. Vous pouvez appeler le président de la république française « Jacques », si vous voulez, mais c'est en réalité une abréviation de son nom complet qui est « Jacques Chirac ». De même, C<$x> a un nom complet qui est quelque chose comme C<$main::x>. La partie B
est l'B, tout comme la partie « Chirac » de « Jacques Chirac ». Jacques Chirac et Jacques Lacan sont des personnes différentes, bien qu'elles se prénomment toutes les deux «EJacquesE». De la même façon, C<$Chirac::Jacques> et C<$Lacan::Jacques> sont des variables différentes, et C<$main::x> et C<$DBI::x> sont des variables différentes. Vous êtes toujours autorisé à inclure la partie du nom de la variable qui désigne le package, et si vous le faites, Perl saura exactement de quelle variable vous parlez. Mais par souci de concision, on aime généralement omettre l'indicateur de package. Que se passe-t-il dans ce cas S =head1 Le package en cours Si vous dites juste C<$x>, Perl considère que vous voulez parler de la variable C<$x> dans le package en cours. Qu'est-ce que le package en S C'est normalement C
, mais vous pouvez le changer en S<écrivant :> package Mypackage; dans votre programme. A partir de là, le package en cours est C. Le seul rôle du package en cours est d'affecter l'interprétation des variables de package que vous nommez sans préciser de nom de package. Si le package en cours est C, alors C<$x> signifie en réalité C<$Mypackage::x>. Si le package en cours est C
, alors C<$x> signifie en réalité C<$main::x>. Si vous écrivez un module, disons le module C, vous mettrez sûrement une ligne comme ceci au début de votre S package MonModule; A partir de là, toutes les variables que vous utilisez se trouvent dans le package C et vous pouvez être pratiquement sûr que ces variables n'entrent pas en conflit avec les variables du reste du programme. Cela n'a pas d'importance si vous et l'auteur de C utilisez une variable appelée C<$x>, parce que l'une sera alors C<$MonModule::x> et l'autre sera C<$DBI::x>. Rappelez vous que les variables de package sont toujours globales. Même si vous n'êtes pas dans le package C, même si vous n'en avez jamais B, rien ne peut vous empêcher de lire et écrire C<$DBI::errstr>. Vous n'avez rien à faire de spécial. C<$DBI::errstr>, comme toutes les variables de package, est une variable globale et elle est disponible globalement. Tout ce que vous avez à faire c'est de l'appeler par son nom complet pour l'atteindre. Vous pourriez même S package DBI; $errstr = 'Ha ha Tim!'; et cela modifierait C<$DBI::errstr>. =head1 Détails triviaux Il y a seulement trois autres choses à savoir à propos des variables de package (vous pouvez les ignorer pour une première lecture)E: =over =item 1 Le package au nom vide est le même que le package C
. Ainsi C<$::x> équivaut à C<$main::x>, quel que soit C. =item 2 Certaines variables sont obligatoirement dans le package main. Par exemple si vous écrivez C<%ENV>, Perl considère que vous parlez de C<%main::ENV>, même si le package en cours n'est pas C
. Si vous voulez parler de C<%Fred::ENV>, vous devez l'appeler explicitement, même si le package en cours est C. Parmi les autre noms ayant cette spécificité on trouve C, tous les noms constitué d'un caractère de ponctuation tels que C<$_> et C<$$> ainsi que C<@ARGV>, C, C et C. =item 3 Les noms de packages peuvent contenir C<::> mais pas les noms de variables. On peut avoir une variable appelée C<$DBD::Oracle::x>. Cela désigne la variable C dans le package C; cela n'a rien à voir avec le package C. Isaac Newton n'a pas de rapport avec Olivia Newton-John, et C n'a pas de rapport avec C. Même s'il apparaît qu'ils commencent tous deux par C, l'apparence est trompeuse. C est dans le package C, pas dans le package Newton. =back C'est tout ce qu'il y a à savoir à propos des variables de package. Les variables de package sont globales, ce qui est dangereux parce que vous ne pouvez jamais être sûr que quelqu'un n'est pas en train de les trifouiller dans votre dos. Jusqu'à Perl 4, toutes les variables était des variables de package, ce qui était embêtant. Perl 5 à apporté de nouvelles variables qui ne sont pas globales. =head1 Les variables lexicales L'autre jeu de variables de Perl s'appelle les B< variables lexicales> (nous verrons pourquoi plus tard) ou les B parce qu'elles sont privées. On peut aussi les appeler parfois B parce qu'elles sont toujours déclarées avec C. Il est tentant de les appelées «Evariables localesE» puisque leur effet est limité à une petite partie du programme, mais ne le faites pas ! Les gens pourraient croire que vous parlez du l'opérateur C de Perl que nous verrons plus tard. Lorsque vous voulez une «Evariable localeE» pensez à C, pas à C. La déclaration my $x; crée une nouvelle variable appelée C, qui est presque totalement inaccessible à la plupart des parties du programme (Tous ce qui se trouve en dehors du bloc où la variable a été déclarée. Ce bloc est appelée la B de la variable. Si la variable n'est pas déclarée dans un bloc, sa portée va de l'endroit où elle a été déclarée à la fin du fichier). On peut aussi déclarer et initialiser une variable my en S<écrivant :> my $x = 119; On peut en déclarer et initialiser plusieurs à la S my ($x, $y, $z, @args) = (5, 23, @_); Voyons un exemple où les variables privées vont être utiles. Examinez ce S sub affiche_rapport { @liste_employes = @_; foreach $employe (@liste_employes) { $salaire = salaire($employee); affiche_rapport_partiel($employe, $salaire); } } S'il se trouve que C utilise aussi une variable appelée C<$employe>, ce sera la même variable que celle utilisée dans C et le fonctionnement pourrait bien être perturbé. Les deux programmeurs responsables de C et C devront se consulter pour être sûr de ne pas utiliser les mêmes variables. C'est un problème. En fait, même dans un projet de taille moyenne, c'est un problème intolérable. La solution consiste à utiliser les variables CE: sub affiche_rapport { my @liste_employes = @_; foreach my $employe (@liste_employes) { my $salaire = salaire($employee); affiche_rapport_partiel($employe, $salaire); } } C crée une nouvelle variable de liste qui est totalement inaccessible en dehors de la fonction C. C crée une nouvelle variable scalaire qui est totalement inaccessible en dehors de la boucle C, tout comme C. Vous n'avez pas à vous préoccuper de savoir si les autres fonctions du programme trifouillent ces variables, elles ne le peuvent pas. Elles ne savent pas où les trouver car les noms ont une signification différente en dehors de la portée des déclarations C. Ces « variables my » sont parfois appelées « lexicales » car leur portée dépend uniquement du texte du programme lui-même et pas des détails de son exécution comme par exemple l'ordre dans lequel les choses sont effectuées. On peut déterminer cette portée en observant le code source, sans même savoir ce qu'il fait. Lorsque vous voyez une variable, chercher une déclaration C plus haut dans le même bloc. Si vous n'en voyez pas dans le plus petit bloc, regardez dans le bloc plus large qui le contient et ainsi de suite jusqu'à ce que vous en trouviez une. Si vous n'en trouvez pas, alors la variable est une variable de package. Les variables C ne sont pas des variables de package. Elles ne font pas partie d'un package et n'ont pas d'indicateur de package. Le package en cours n'a aucun effet sur la façon dont elles sont interprétées. Voici un S my $x = 17; package A; $x = 12; package B; $x = 20; # $x vaut maintenant 20. # $A::x et $B::x sont toujours indéfinies C change le package en cours, mais comme C<$x> fait référence à une variable lexicale, et non à une variable de package, C<$x=12> n'a aucun effet sur C<$A::x>. De même, après C, C<$x=20> modifie la variable lexicale et non l'une des variables de package. À la fin du fichier, la variable lexicale C<$x> contient 20 et les variables de package C<$main::x>, C<$A::x>, et C<$B::x> sont toujours indéfinies. Si vous en aviez eu besoin, vous auriez toujours pu y accéder en utilisant leurs noms complets. La phrase à retenir S «ELes variables de package sont des variables globales.E» Pour les variables privées, il faut utiliser C. =head1 local et my Presque tout le monde sait qu'il y a une fonction C en rapport avec les variables locales. Qu'est-ce que c'est, et qu'est-ce que ça a à voir avec S ?> La réponse est simple, mais S<étrange :> C crée une variable locale. C ne fait pas cela. D'abord, voici ce que fait vraiment S :> ça sauve la valeur actuelle de la variable de package C<$x> dans un endroit sûr et ça la remplace par une nouvelle valeur ou par C si aucune nouvelle valeur n'a été spécifiée. L'ancienne valeur est restaurée lorsqu'on quitte le bloc en cours. Les variables affectées sont des variables de package auxquelles on attribue une valeur Ce. Mais les variables de package sont toujours globales, et une une variable de package Ce ne fait pas exception. Pour voir la différence, essayer S $lo = 'global'; $m = 'global'; A(); sub A { local $lo = 'AAA'; my $m = 'AAA'; B(); } sub B { print "B ", ($lo eq 'AAA' ? 'peut' : 'ne peut pas') , " voir la valeur de lo assignée par A.\n"; print "B ", ($m eq 'AAA' ? 'peut' : 'ne peut pas') , " voir la valeur de m assignée par A.\n"; } Cela S B peut voir la valeur de lo assignée par A. B ne peut pas voir la valeur de m assignée par A. Que s'est-il S La déclaration C dans C a sauvé une nouvelle variable temporaire, C, dans la variable de package C<$lo>. L'ancienne valeur, C, sera restaurée une fois que C sera terminée, mais avant que cela se produise, C appelle C. C n'a pas de problème pour accéder au contenu de C<$lo> puisque C<$lo> est une variable de package et les variables de package sont toujours accessibles de partout. Ainsi elle voit la valeur C assignée par C. Au contraire, C a créé une nouvelle variable, C<$m>, de portée lexicalement limitée, qui est uniquement visible à l'intérieur de la fonction C. En dehors de C, C<$m> garde son ancienne S elle fait référence à la variable de package C<$m> qui est toujours Ce. C'est la variable que C voit. Elle ne voit pas la valeur C parce que la variable qui a cette valeur est une variable lexicale et existe seulement à l'intérieur de C. =head1 A quoi sert S Comme C ne crée en fait pas de variable locale, il n'est pas très utile. Si, dans l'exemple ci-dessus, C venait à modifier la valeur de C<$lo>, alors la valeur assignée pas C serait écrasée. C'est exactement ce que nous ne voulons pas qu'il se produise. Nous voulons que chaque fonction ait ses propres variables qui soient inaccessibles par les autres. C'est ce que fait C. Pourquoi C existe S La réponse est à 90% historique. Les premières version de Perl n'avait que des variables globales. C était facile à implémenter et a été ajouté à Perl 4 comme une solution partielle au problème des variables locales. Plus tard, dans Perl 5, plus de travail a été accompli, et de vraies variables locales ont été ajoutées au langage. Mais le nom C était déjà pris, alors la nouvelle fonctionnalité a été appelée C. C a été choisie parce qu'elle suggère l'idée de privé et aussi parce que c'est très court. La petitesse du mot est supposée vous encourager à l'utiliser à la place de C. C est également plus rapide que C. =head1 Quand utiliser my et quand utiliser S Toujours utiliser C ; ne jamais utiliser C. Facile, S =head1 Autres propriétés des variables my À chaque déclaration C, Perl crée une toute nouvelle variable. Ce code, par exemple, affiche cinquante fois C. for (1 .. 50) { my $x; $x++; print "x=$x\n"; } Vous obtenez un nouveau C<$x> initialisé à C à chaque tour de boucle. Si la déclaration était à l'extérieur de la boucle, elle ne serait effectuée qu'une seule fois, nous n'aurions donc qu'une seule variable. { my $x; for (1 .. 50) { $x++; print "x=$x\n"; } } Cela affiche C, C, C, ... C. Vous pouvez utiliser cela pour un truc utileE: dans une fonction qui a besoin de mémoriser une valeur d'un appel à l'autre. Par exemple considérons un générateur de nombres aléatoires (comme la fonction C de Perl). Un générateur de nombres aléatoires classique possède une B (NDT: "seed" en anglais). Cette graine est simplement un nombre. Quand vous demandez un nombre aléatoire, la fonction fait des opérations arithmétiques qui brouillent la graine, et elle renvoie le résultat. Elle sauve également le résultat et l'utilise comme graine lors de l'appel suivant. Voici le code S (Je l'ai volé au C ANSI standard, mais il n'est pas terrible, alors ne l'utilisez pas pour quelque chose d'important). $seed = 1; sub my_rand { $seed = int(($seed * 1103515245 + 12345) / 65536) % 32768; return $seed; } Et sa sortie S 16838 14666 10953 11665 7451 26316 27974 27550 Mais il y a un problème, C<$seed> est une variable globale, ce qui signifie que nous devons vérifier que personne ne la modifie par inadvertance. Ou bien il pourrait y toucher en connaissance de cause, ce qui aurait des conséquences sur le reste du programme. Qu'adviendrait-il, par exemple, s'il s'agissait d'un programme de jeu et que quelqu'un vienne tripoter le générateur de nombres S Mais nous ne pouvons pas déclarer C<$seed> comme un variable C dans la S sub my_rand { my $seed; $seed = int(($seed * 1103515245 + 12345) / 65536) % 32768; return $seed; } En effet elle serait initialisée à C chaque fois que nous appelons C. Nous avons besoin de retenir sa valeur entre les appels de C. Voici la S { my $seed = 1; sub my_rand { $seed = int(($seed * 1103515245 + 12345) / 65536) % 32768; return $seed; } } La déclaration est en dehors de la fonction, ainsi elle ne se produit qu'une fois, lorsque le programme est compilé, pas à chaque fois que la fonction est appelée. Mais c'est une variable C, et elle est dans un bloc, ce qui la rend accessible uniquement au code situé à l'intérieur du bloc. C est la seule autre chose dans le bloc, donc la variable C<$seed> est seulement accessible à la fonction C. C<$seed> est parfois appelée une variable statique parce qu'elle reste la même entre les appels de fonction (et aussi parce il y a une fonctionnalité équivalente en C qui est spécifiée par le mot-clé C). =head1 my Variable Trivia (NDT: si vous savez traduire ce titre, faites moi S) Vous ne pouvez pas déclarer une variable C si son nom est un signe de ponctuation, comme C<$_>, C<@_> ou C<$$>. Vous ne pouvez pas non plus déclarer ainsi les variables de référence arrière C<$1>, C<$2>, etc. Les auteurs de C ont pensé que cela prêterait à confusion. Bien sûr, vous ne pouvez pas dire C, car se serait contradictoire, cela reviendrait à dire que la variable de package C<$DBI::errstr> est à présent une variable lexicale. Mais vous B dire C, ce qui sauvegarde la valeur actuelle de C<$DBI::errstr> et fait en sorte qu'elle soit restituée à la fin du bloc. Depuis Perl 5.004, on peut S<écrire :> foreach my $i (@list) { Ce qui confine le C<$i> dans la portée de la boucle. De même, for (my $i=0; $i<100; $i++) { limite la portée de C<$i> à la boucle C. =head1 Déclarations Si vous écrivez une fonction et que vous voulez qu'elle ait des variables privées, vous devez déclarer les variables avec C. Que se passe-t-il si vous S sub function { $x = 42; # Oops, on aurait du écrire my $x = 42. } Dans ce cas, votre fonction modifie la variable de package globale C<$x>. Si vous utilisez cette variable pour autre chose, ce sera un désastre pour votre programme. Les versions récentes de Perl on un protection optionnelle contre cela que vous pouvez activer si vous le souhaiter. Si vous mettez use strict 'vars'; en haut de votre programme, Perl va B que ces variables de package aient un indicateur de package explicite. Le C<$x> dans C<$x=42> n'a pas d'indicateur, alors le programme ne va même pas se compiler. Le compilateur va abandonner et donner le message S Global symbol "$x" requires explicit package name at ... Si vous voulez que C<$x> soit une variable C privée, vous pouvez revenir en arrière et ajouter le C. Si vous voulez vraiment utiliser la variable de package globale, vous pouvez remplacer par $main::x = 42; ou un autre nom de package approprié. Dire simplement C active C, et plusieurs autres vérifications. Voir C pour plus de détails. À présent supposons que vous écrivez le module C et que vous voulez la protection de C mais que vous craignez de ne pas pouvoir finir le module à cause de crampes aux doigts à force de taper C<$Algorithms::KnuthBendix::Error> tout le temps. Vous pouvez sauver vos doigts en disant à C de faire une S package Algorithms::KnuthBendix; use vars '$Error'; Cela évite que la variable C<$Algorithms::KnuthBendix::Error> cause une erreur due à C si vous y faites référence par son nom court C<$Error>. Vous pouvez aussi désactiver C pour la portée du bloc en S<écrivant :> { no strict 'vars'; # strict vars est inactif jusqu'à la fin du bloc ... } =head1 Pour résumer Les variables de package sont toujours globales. Elles ont un nom et un indicateur de package. Vous pouvez omettre les indicateurs de package, auquel cas Perl utilise le package par défaut, que vous pouvez définir par la déclaration C. Pour des variables privées, utilisez C. N'utilisez pas C, c'est obsolète. Vous devriez éviter les variables globales parce que ça peut être dur d'être sûr que deux parties du programme n'utilisent pas les variables des autres par erreur. Pour éviter d'utiliser des variables globales par accident, ajoutez C à votre programme. Cela vérifie que toutes vos variables sont soit déclarées comme privées, soit qualifiées explicitement, soit explicitement déclarées avec C. =head1 Notes Certains se sont plaint de ma maxime «ENe jamais utiliser C.E». Mais dans 97% des cas, cette maxime est parfaitement exacte. C peut être utile, mais rarement, alors je les ai laissées de côté car l'objectif d'un tutoriel est de présenter 97% d'utilité dans 50% d'espace. J'étais quand même embêté d'avoir beaucoup de mails rébarbatifs me disant « Tu as oublié de mentionner que C peut servir à ceci ou cela, tu sais ». Alors j'ai écrit l'article B pour me débarrasser des gens qui me fatiguaient avec C. Voici un autre sujet intéressant que j'ai laissé de côté par souci de clarté et pour ne pas surcharger. J'ai reçu un mail de Robert Watkins à propos d'un programme qu'il avait écrit et qui ne fonctionnait pas. Voici à quoi ressemblait le S my $x; for $x (1..5) { s(); } sub s { print "$x, " } Robert voulait afficher C<1, 2, 3, 4, 5,> mais ça ne marchait pas. À la place, cela affichait C<, , , , , >. Où étaient donc passées les valeurs de S ?> Le truc ici c'est que normalement, quand vous écrivez quelque chose comme S<ça :> for $x (...) { } Perl veut confiner la valeur de la variable d'index à l'intérieur de la boucle. Si C<$x> est une variable de package, il fait comme si vous aviez S<écrit :> { local $x; for $x (...) { } } En revanche, si C<$x> est une variable lexicale, il fait comme si vous aviez S<écrit :> { my $x; for $x (...) { } } cela signifie que la variable d'index de boucle ne sera pas propagée aux sous-programmes, même si elle est dans la portée de la déclaration originale. J'aurais probablement pu éviter de faire aussi long puisque la page de manuel B décrit cela très S «E...la variable est implicitement locale à la boucle et reprend sa valeur précédente à la sortie de la boucle. Si la variable était précédemment déclaré par my, elle utilise cette variable au lieu de celle qui est globale, mais elle est toujours locale à la boucle. (A noter qu'une variable de portée lexicale peut poser des problèmes si vous avez un sous-programme ou une déclaration de format à l'intérieur de la boucle qui y fait référence.)E» À mon avis, donner une portée lexicale à la variable d'index était sûrement une erreur. Si vouliez ça, vous auriez écrit C à la place. J'aurais aimé que ça localise la variable S ça aurait sauvé la valeur de la variable lexicale avant la boucle et ça l'aurait restauré après la boucle. Mais pour des raisons techniques c'est impossible parce que ça ne marche pas non S my $m; { local $m = 12; ... } Le C échoue avec ce message S Can't localize lexical variable $m... Il y a eu une discussion sur P5P à propos de l'éventualité de rendre cela possible, mais ça n'a pas l'air trivial. Ajouté le S<05/01/2001 :> Il y a une petite saloperie qui prends les gens par surprise. Soit le programme S use strict 'vars'; my @lines = <>; my @sorted = sort backwards @lines; print @sorted; sub backwards { $b cmp $a } Ici nous n'avons déclaré ni C<$a>, ni C<$b>, ce sont donc des variables globales. En fait, il est nécessaire qu'elles soient globales parce que l'opérateur C doit être capable de les affecter pour la fonction C. Pourquoi C ne provoque-t-il pas une S Les variables C<$a> et C<$b> sont épargnées par la vérification de C exactement pour cette raison. =head1 AUTEUR Mark Jason Dominus =head1 VERSION ORIGINALE http://perl.plover.com/FAQs/Namespaces.html (S :> ce document est dynamique et choisit sa langue en fonction de celles demandées par votre navigateur.) =head1 TADUCTION Alex Marandon