=encoding iso-8859-1 =head1 NOM perlsub - Les Sous-Programmes de Perl =head1 SYNOPSIS Pour déclarer des sous-programmes : sub NAME; # Une déclaration "en avant". sub NAME(PROTO); # idem, mais avec des prototypes sub NAME BLOCK # Une déclaration et une définition. sub NAME(PROTO) BLOCK # idem, mais avec des prototypes Pour définir un sous-programme anonyme lors de l'exécution : $subref = sub BLOCK; # pas de prototype $subref = sub (PROTO) BLOCK; # avec prototype Pour importer des sous-programmes : use PACKAGE qw(NAME1 NAME2 NAME3); Pour appeler des sous-programmes : NAME(LIST); # & est optionnel avec les parenthèses. NAME LIST; # Les parenthèses sont optionnelles si le # sous-programme est prédéclaré ou importé. &NAME; # Rend la @_ courante visible par le # sous-programme appelé. =head1 DESCRIPTION Comme beaucoup de langages, Perl fournit des sous-programmes définis par l'utilisateur. Ils peuvent se trouver n'importe où dans le programme principal, ils peuvent être chargés depuis d'autres fichiers via les mots-clés C, C, ou C, ou même être générés à la volée en utilisant C ou des sous-programmes anonymes (fermetures). Vous pouvez même appeler une fonction indirectement en utilisant une variable contenant son nom ou une référence de CODE pointant sur lui. Le modèle de Perl pour l'appel de fonction et le renvoi de valeurs est simple : tous les paramètres sont passés aux fonctions comme une seule simple liste de scalaires, et toutes les fonctions renvoient de la même manière à leur appelant une seule simple liste de scalaires. Tout tableau ou hachage dans ces listes d'appel et de retour s'effondreront, perdant leur identité -- mais vous pouvez toujours utiliser le passage par référence à la place pour éviter cela. Les listes d'appel ou de retour peuvent contenir autant d'éléments scalaires que vous le désirez (une fonction sans instruction de retour explicite est souvent appelée un sous-programme, mais il n'y a vraiment pas de différence dans la perspective du langage). Tous les arguments passés à la routine entrent par l'intermédiaire du tableau C<@_>. Ainsi, si vous appelez une fonction avec deux arguments, ceux-ci seront stockés dans C<$_[0]> et C<$_[1]>. Le tableau C<@_> est un tableau local, mais ses éléments sont des alias pour les véritables paramètres scalaires. En particulier, si un élément C<$_[0]> est mis à jour, l'argument correspondant est mis à jour (ou bien une erreur se produit s'il n'est pas modifiable). Si un argument est un élément de tableau ou de hachage qui n'existait pas lors de l'appel de la fonction, cet élément est créé seulement lorsque (et si) il est modifié ou si on y fait référence (certaines versions précédentes de Perl créaient l'élément qu'il soit ou non affecté). Notez que l'affectation à la totalité du tableau C<@_> retire les alias, et ne met à jour aucun argument. La valeur de retour du sous-programme est la valeur de la dernière expression évaluée. Alternativement, une instruction C peut être utilisée pour sortir du sous-programme, en spécifiant de façon optionnelle la valeur de retour, qui sera évaluée dans le contexte approprié (liste, scalaire, ou vide) selon le contexte de l'appel du sous-programme. Si vous ne spécifiez pas de valeur de retour, le sous-programme renverra une liste vide dans un contexte de liste, une valeur indéfinie dans un contexte scalaire, ou rien dans un contexte vide. Si vous renvoyez un ou plusieurs tableau(x) et/ou hachage(s), ils seront aplatis ensemble indistinctement en une seule grosse liste. Perl n'a pas de paramètres formels nommés, mais en pratique tout ce que vous avez à faire est d'affecter à une liste C les contenant. Toutes les variables que vous utilisez dans la fonction et qui ne sont pas déclarées comme privées sont des variables globales. Pour les détails sanglants sur la création de variables privées, voir L<"Variables Privées via my()"> et L<"Valeurs Temporaires via local()">. Pour créer des environnement protégés pour un ensemble de fonctions dans un paquetage séparé (et probablement un fichier séparé), voir L. Exemple : sub max { my $max = shift(@_); foreach $foo (@_) { $max = $foo if $max < $foo; } return $max; } $bestday = max($mon,$tue,$wed,$thu,$fri); Exemple : # obtient une ligne, en y combinant les lignes la continuant qui # débutent par un blanc sub get_line { $thisline = $lookahead; # VARIABLES GLOBALES !! LINE: while (defined($lookahead = )) { if ($lookahead =~ /^[ \t]/) { $thisline .= $lookahead; } else { last LINE; } } $thisline; } $lookahead = ; # obtient la première ligne while ($_ = get_line()) { ... } Utilisation d'une affectation de tableau à une liste locale pour nommer vos arguments formels : sub maybeset { my($key, $value) = @_; $Foo{$key} = $value unless $Foo{$key}; } Ceci a aussi pour effet de transformer l'appel par référence en appel par valeur, car l'affectation copie les valeurs. Autrement, une fonction est libre de faire des modifications de C<@_> sur place et de changee les valeurs de son appelant. upcase_in($v1, $v2); # ceci change $v1 et $v2 sub upcase_in { for (@_) { tr/a-z/A-Z/ } } Vous n'avez pas le droit de modifier les constantes de cette façon, bien sûr. Si un argument était en vérité un littéral et que vous essayiez de le changer, vous lèveriez une exception (probablement fatale). Par exemple, ceci ne fonctionnera pas : upcase_in("frederick"); Ce serait bien plus sûr si la fonction C était écrite de façon à renvoyer une copie de ses paramètres au lieu de les changer sur place : ($v3, $v4) = upcase($v1, $v2); # this doesn't (NDT : ??) sub upcase { return unless defined wantarray; # contexte vide, ne fait rien my @parms = @_; for (@parms) { tr/a-z/A-Z/ } return wantarray ? @parms : $parms[0]; } Notez comment cette fonction (non prototypée) ne se soucie pas qu'on lui ait passé de vrais scalaires ou des tableaux. Perl verra tout comme une grosse et longue liste plate de paramètres C<@_>. C'est l'une des manière qu'à le simple passage d'argument en Perl de briller. La fonction C fonctionnerait parfaitement bien sans avoir à changer la définition de C même si nous lui donnions des choses telles que ceci : @newlist = upcase(@list1, @list2); @newlist = upcase( split /:/, $var ); Ne vous laissez toutefois pas tenter de faire : (@a, @b) = upcase(@list1, @list2); Parce que tout comme sa liste plate de paramètres entrante, la liste de retour est plate. Donc tout ce que vous êtes parvenu à faire ici est de tout stocker dans C<@a> et de faire de C<@b> une liste vide. Voir L pour des alternatives. Un sous-programme peut être appelé en utilisant le préfixe "C<&>". Le "C<&>" est optionnel dans les Perls modernes, tout comme le sont les parenthèses si le sous-programme a été prédéclaré (Notez toutefois que le "C<&>" n'est I optionnel lorsque vous nommez juste le sous-programme, comme par exemple lorsqu'il est utilisé comme argument de C ou C. Il n'est pas non plus optionnel lorsque vous voulez faire un appel indirect de sous-programme avec le nom d'un sous-programme ou une référence utilisant les constructions C<&$subref()> ou C<&{$subref}()>. Voir L pour plus de détails). Les sous-programmes peuvent être appelés de façon récursive. Si un sous-programme est appelé en utilisant la forme "C<&>", la liste d'arguments est optionnelle, et si elle est omise, aucun tableau C<@_> n'est mis en place pour le sous-programme : le tableau C<@_> au moment de l'appel est visible à la place dans le sous-programme. C'est un mécanisme d'efficacité que les nouveaux utilisateurs pourraient préférer éviter. &foo(1,2,3); # passe trois arguments foo(1,2,3); # idem foo(); # passe une liste nulle &foo(); # idem &foo; # foo() obtient les arguments courants, comme foo(@_) !! foo; # comme foo() SI le sous-programme foo est # prédéclaré, sinon "foo" Non seulement la forme "C<&>" rend la liste d'arguments optionnelle, mais elle désactive aussi toute vérification de prototype sur les arguments que vous fournissez. C'est en partie pour des raisons historiques, et en partie pour avoir une façon pratique de tricher si vous savez ce que vous êtes en train de faire. Voyez la section sur les Prototypes ci-dessous. Les fonctions dont les noms sont entièrement en majuscules sont réservées pour le noyau de Perl, tout comme les modules dont les noms sont entièrement en minuscules. Une fonction entièrement en majuscules est une convention informelle signifiant qu'elle sera appelée indirectement par le système d'exécution lui-même. Les fonctions qui font des choses spéciales prédéfinies sont C, C, C, et C -- plus toutes les fonctions mentionnées dans L. La version 5.005 ajoute C à cette liste. =head2 Variables Privées via my() Synopsis: my $foo; # déclare $foo locale lexicalement my (@wid, %get); # déclare une liste de variables locale my $foo = "flurp"; # déclare $foo lexical, et l'initialise my @oof = @bar; # déclare @oof lexical, et l'initialise Un "C" déclare que les variables listées doivent être confinées (lexicalement) au bloc où elles se trouvent, dans la conditionnelle (C), la boucle (C), le sous-programme, l'C, ou le fichier exécuté, requis ou utilisé via C. Si plus d'une valeur est listée, la liste doit être placée entre parenthèses. Tous les éléments listés doivent être des lvalues légales. Seuls les identifiants alphanumériques peuvent avoir une portée lexicale -- les identifiants magiques prédéfinis comme C<$/> doivent actuellement être à la place Cisés par "C". Contrairement aux variables dynamiques créées par l'opérateur "C", les variables lexicales déclarées par "C" sont totalement cachées du monde extérieur, y compris de tout sous-programme appelé (même si c'est le même sous-programme qui est appelé depuis lui-même ou d'ailleurs -- chaque appel obtient sa propre copie). Ceci ne veut pas dire qu'une variable C déclarée dans une portée lexicale I statiquement serait invisible. Seules les portées dynamiques sont rétrécies. Par exemple, la fonction C ci-dessous a accès à la variable lexicale C<$x> car le my et le sub se sont produits dans la même portée, probablement la portée du fichier. my $x = 10; sub bumpx { $x++ } (Un C, toutefois, peut voir les variables lexicales de la portée dans laquelle il est évalué tant que les noms ne sont pas cachés par des déclarations à l'intérieur de l'C lui-même. Voir L). La liste de paramètres de C peut être affectée si on le désire, ce qui vous permet d'initialiser vos variables (si aucune valeur initiale n'est donnée à une variable particulière, celle-ci est créé avec la valeur indéfinie). Ceci est utilisé couramment pour nommer les paramètres d'un sous-programme. Exemples : $arg = "fred"; # variable "globale" $n = cube_root(27); print "$arg thinks the root is $n\n"; fred thinks the root is 3 sub cube_root { my $arg = shift; # le nom n'importe pas $arg **= 1/3; return $arg; } Le "C" est simplement un modificateur sur quelque chose que vous pourriez affecter. Donc lorsque vous affectez les variable dans sa liste d'arguments, le "C" ne change pas le fait que ces variables soient vues comme un scalaire ou un tableau. Donc my ($foo) = ; # FAUX ? my @FOO = ; les deux fournissent un contexte de liste à la partie droite, tandis que my $foo = ; fournit un contexte scalaire. Mais ce qui suit ne déclare qu'une seule variable : my $foo, $bar = 1; # FAUX Cela a le même effet que my $foo; $bar = 1; La variable déclarée n'est pas introduite (n'est pas visible) avant la fin de l'instruction courante. Ainsi, my $x = $x; peut être utilisé pour initialiser la nouvelle variable $x avec la valeur de l'ancienne C<$x>, et l'expression my $x = 123 and $x == 123 est fausse à moins que l'ancienne variable C<$x> ait la valeur C<123>. Les portées lexicales de structures de contrôle ne sont pas précisément liées aux accolades qui délimitent le bloc qu'elles contrôlent ; les expressions de contrôle font aussi partie de la portée. Ainsi, dans la boucle while (defined(my $line = <>)) { $line = lc $line; } continue { print $line; } la portée de C<$line> s'étend à partir de sa déclaration et sur tout le reste de la boucle (y compris la clause C), mais pas au-delà. De façon similaire, dans la conditionnelle if ((my $answer = ) =~ /^yes$/i) { user_agrees(); } elsif ($answer =~ /^no$/i) { user_disagrees(); } else { chomp $answer; die "'$answer' is neither 'yes' nor 'no'"; } la portée de C<$answer> s'étend à partir de sa déclaration et sur tout le reste de la conditionnelle (y compris les clauses C et C, s'il y en a), mais pas au-delà. (Rien de ce qui précède ne s'applique aux modificateurs C et C ajoutés à d'autres instructions simples. De tels modificateurs ne sont pas des structures de contrôle et n'ont pas d'effets sur la portée). La boucle C a pour défaut de donner une portée dynamiquement a sa variable d'index (à la manière de C ; voir ci-dessous). Toutefois, si la variable d'index est préfixée avec le mot-clé "C", alors elle a à la place une portée lexicale. Ainsi dans la boucle for my $i (1, 2, 3) { some_function(); } la portée de C<$i> s'étend jusqu'à la fin de la boucle, mais pas au-delà, et ainsi la valeur de C<$i> n'est pas disponible dans C. Certains utilisateurs pourraient désirer encourager l'usage de variables à portée lexicale. Comme aide pour intercepter les références implicites à des variables de paquetage, si vous dites use strict 'vars'; alors toute référence de variable à partir de là jusqu'à la fin du bloc doit soit se référer à une variable lexicale, soit doit être totalement qualifiée avec le nom du paquetage. Autrement, une erreur de compilation se produit. Un bloc interne pourrait contrer ceci par S<"C">. Un C a un effet à la fois à la compilation et lors de l'exécution. Lors de la compilation, le compilateur le remarque ; la principale utilité de ceci est de faire taire S<"C">. L'initialisation effective est retardée jusqu'à l'exécution, de façon à ce qu'elle soit exécutée correctement ; chaque fois que la boucle est traversée, par exemple. Les variables déclarées avec "C" ne font pas partie d'un paquetage et ne sont par conséquent jamais totalement qualifiée avec le nom du paquetage. En particulier, vous n'avez pas le droit d'essayer de rendre lexicale une variable de paquetage (ou toute autre variable globale) : my $pack::var; # ERREUR ! Syntaxe Illégale my $_; # aussi illégal (pour le moment) En fait, une variable dynamique (aussi connue sous le nom de variable de paquetage ou variable globale) est toujours accessible en utilisant la notation totalement qualifiée C<::> même lorsqu'un lexical de même nom est lui aussi visible : package main; local $x = 10; my $x = 20; print "$x and $::x\n"; Ceci affichera C<20> et C<10>. Vous pouvez déclarer les variables "C" dans la portée extrême d'un fichier pour cacher totalement tous ces identifants du monde extérieur. Cela est similaire aux variables statiques de C au niveau du fichier. Faire cela avec un sous-programme requiert l'usage d'une fermeture (fonction anonyme avec accès lexical). Si un bloc (tel qu'un C, une fonction ou un C) veut créer un sous-programme privé qui ne puisse pas être appelé de l'extérieur de ce bloc, il peut déclarer une variable lexicale contenant une référence anonyme de sous-programme : my $secret_version = '1.001-beta'; my $secret_sub = sub { print $secret_version }; &$secret_sub(); Tant que la référence n'est jamais renvoyée par aucune fonction du module, aucun module extérieur ne peut voir le sous-programme, car son nom n'est dans la table de symboles d'aucun paquetage. Souvenez-vous qu'il n'est jamais I appelé C<$some_pack::secret_version> ou quoi que ce soit ; c'est juste C<$secret_version>, non qualifié et non qualifiable. Ceci ne fonctionne pas avec les méthodes d'objets, toutefois ; toutes les méthodes d'objets doivent se trouver dans la table de symboles d'un paquetage quelconque pour être trouvées. =head2 Variables Privées Persistantes Le fait qu'une variable lexicale ait une portée lexicale (aussi appelée statique) égale au bloc qui la contient, à l'C, ou au FICHIER C, ne veut pas dire que cela fonctionne à l'intérieur d'une fonction comme une variable statique en C. Cela marche normalement plus comme une variable auto de C, mais avec un ramassage des miettes (garbage collection, NDT) implicite. Contrairement aux variables locales en C ou en C++, les variables lexicales de Perl ne sont pas nécessairement recyclées juste parce qu'on est sorti de leur portée. Si quelque chose de plus permanent est toujours conscient du lexical, il restera. Tant que quelque chose d'autre fait référence au lexical, ce lexical ne sera pas libéré -- ce qui est comme il se doit. Vous ne voudriez pas que la mémoire soit libérée tant que vous n'avez pas fini de l'utiliser, ou gardée lorsque vous en avez terminé. Le ramasse-miette automatique s'occupe de cela pour vous. Ceci veut dire que vous pouvez passer en retour ou sauver des références à des variables lexicales, tandis que retourner un pointeur sur un auto en C est une grave erreur. Cela nous donne aussi un moyen de simuler les variables statiques de fonctions C. Voici un mécanisme donnant à une fonction des variables privées de portée lexicale ayant une durée de vie statique. Si vous désirez créer quelque chose ressemblant aux vatiables statiques de C, entourez juste toute la fonction d'un niveau de bloc supplémentaire, et mettez la variable statique hors de la fonction mais dans le bloc. { my $secret_val = 0; sub gimme_another { return ++$secret_val; } } # $secret_val devient désormais impossible à atteindre pour le # monde extérieur, mais garde sa valeur entre deux appels à # gimme_another Si cette fonction est chargée par C ou C depuis un fichier séparé, alors cela marchera probablement très bien. Si tout se trouve dans le programme principal, vous devrez vous arranger pour que le C soit exécuté tôt, soit en mettant tout le bloc avant votre programme principal, ou, de préférence, en plaçant simplement un sous-programme C autour de lui pour vous assurer qu'il soit exécutée avant que votre programme ne démarre : sub BEGIN { my $secret_val = 0; sub gimme_another { return ++$secret_val; } } Voir L au sujet de la fonction C. S'ils sont déclarés au niveau de la plus grande portée, celle du fichier, alors les lexicaux fonctionnent un peu comme les variables statiques de fichier en C. Ils sont disponibles pour toutes les fonctions déclarées en dessous d'eux dans le même fichier, mais sont inaccessibles hors du fichier. C'est parfois utilisé dans les modules pour créer des variables privées pour tout le module. =head2 Valeurs Temporaires via local() B: En général, vous devriez utiliser "C" au lieu de "C", parce que c'est plus rapide et plus sûr. Des exceptions à cela incluent les variables globales de ponctuation, les handles de fichier et les formats, et la manipulation directe de la table de symboles de Perl elle-même. Les variables de format utilisent toutefois souvent "C", tout comme les autres variables dont la valeur courante doit être visible par les sous-programmes appelés. Synopsis : local $foo; # déclare $foo locale dynamiquement local (@wid, %get); # déclare une liste de variables locales local $foo = "flurp"; # déclare $foo dynamique, et l'initialise local @oof = @bar; # déclare @oof dynamique, et l'initialise local *FH; # rend locales $FH, @FH, %FH, &FH... local *merlyn = *randal; # maintenant $merlyn est vraiment $randal, plus # @merlyn est vraiment @randal, etc local *merlyn = 'randal'; # MÊME CHOSE : 'randal' est promu *randal local *merlyn = \$randal; # alias juste $merlyn, pas @merlyn etc Un C modifie ses variables listées pour qu'elle soient "locales" au bloc courant, à l'C, ou au FICHIER C -- et à I. Un C donne juste des valeurs temporaires aux variables globales (au paquetage). Il ne crée B une variable locale. Ceci est connu sous le nom de portée dynamique. La portée lexicale est créé par "C", qui fonctionne plus comme les déclarations auto de C. Si plus d'une variable est donnée à C, elles doivent être placées entre parenthèses. Tous les éléments listés doivent être des lvalues légales. Cet opérateur fonctionne en sauvegardant les valeurs courantes de ces variables dans sa liste d'arguments sur une pile cachée et les restaure à la sortie du bloc, du sous-programme ou de l'eval. Ceci veut dire que les sous-programmes appelés peuvent aussi référencer les variables locales, mais pas les globales. La liste d'arguments peut être affectée si l'on veut, ce qui vous permet d'initialiser vos variables locales (si aucun initialiseur n'est donné pour une variable locale particulière, elle est créée avec la valeur indéfinie). C'est couramment utilisé pour nommer les paramètres d'un sous-programme. Exemples : for $i ( 0 .. 9 ) { $digits{$i} = $i; } # présume que cette fonction utilise le hachage global %digits parse_num(); # on ajoute maintenant temporairement au hachage %digits if ($base12) { # (NOTE : on ne prétend pas que ce soit efficace !) local %digits = (%digits, 't' => 10, 'e' => 11); parse_num(); # parse_num obtient ce nouveau %digits ! } # l'ancien %digits est restauré ici Puisque C est une commande réalisée lors de l'exécution, elle est exécutée chaque fois que l'on travers une boucle (Au relecteur : exécution - exécutéé, bof). Dans les versions de Perl antérieures à la 5.0, ceci consommait chaque fois un peu plus de place sur la pile jusqu'à la sortie de la boucle. Perl récupère désormais cette place à chaque fois, mais il est toujours plus efficace de déclarer vos variables hors de la boucle. Un C est simplement un modificateur d'une expression donnant une lvalue. Lorsque vous affectez une variable Cisée, le C ne change pas selon que sa liste est vue comme un scalaire ou un tableau. Donc local($foo) = ; local @FOO = ; fournissent tous les deux un contexte de liste à la partie droite, tandis que local $foo = ; fournit un contexte scalaire. Une note sur C et les types composés est nécessaire. Quelque chose comme C fonctionne en plaçant temporairement un hachage tout neuf dans la table des symboles. L'ancien hachage est mis de côté, mais est caché "derrière" le nouveau. Ceci signifie que l'ancienne variable est complètement invisible via la table des symboles (i.e. l'entrée de hachage dans le typeglob C<*foo>) pendant toute la durée de la portée dynamique dans laquelle le C a été rencontré. Cela a pour effet de permettre d'occulter temporairement toute magie sur les types composés. Par exemple, ce qui suit altèrera brièvement un hachage lié à une autre implémentation : tie %ahash, 'APackage'; [...] { local %ahash; tie %ahash, 'BPackage'; [.. le code appelé verra %ahash lié à 'BPackage'..] { local %ahash; [..%ahash est une hachage normal (non lié) ici..] } } [..%ahash revient à sa nature liée initiale..] Autre exemple, une implémentation personnelle de C<%ENV> pourrait avoir l'air de ceci : { local %ENV; tie %ENV, 'MyOwnEnv'; [..faites vos propres manipulations fantaisistes de %ENV ici..] } [..comportement normal de %ENV ici..] Il vaut aussi la peine de prendre un moment pour expliquer ce qui se passe lorsque vous Cisez un membre d'un type composé (i.e. un élément de tableau ou de hachage). Dans ce cas, l'élément est Cisé I. Cela veut dire que lorsque la portée du C se termine, la valeur sauvée sera restaurée dans l'élément du hachage dont la clé a été nommée dans le C, ou dans l'élément du tableau dont l'index a été nommé dans le C. Si cet élément a été effacé pendant que le C faisait effet (e.g. par un C dans un hachage ou un C d'un tableau), il reprendra vie, étendant potentiellement un tableau et remplissant les éléments intermédiaires avec C. Par exemple, si vous dites %hash = ( 'This' => 'is', 'a' => 'test' ); @ary = ( 0..5 ); { local($ary[5]) = 6; local($hash{'a'}) = 'drill'; while (my $e = pop(@ary)) { print "$e . . .\n"; last unless $e > 3; } if (@ary) { $hash{'only a'} = 'test'; delete $hash{'a'}; } } print join(' ', map { "$_ $hash{$_}" } sort keys %hash),".\n"; print "The array has ",scalar(@ary)," elements: ", join(', ', map { defined $_ ? $_ : 'undef' } @ary),"\n"; Perl affichera 6 . . . 4 . . . 3 . . . This is a test only a test. The array has 6 elements: 0, 1, 2, undef, undef, 5 Notez aussi que lorsque vous Cisez un membre d'un type composé qui B, la valeur est traitée comme si elle était dans un contexte de lvalue, i.e., elle est d'abord créé puis Cisée. La conséquence en est que le hachage ou le tableau est en fait modifié de façon permanente. Par exemple, si vous dites %hash = ( 'This' => 'is', 'a' => 'test' ); @ary = ( 0..5 ); { local($ary[8]) = 0; local($hash{'b'}) = 'whatever'; } printf "%%hash has now %d keys, \@ary %d elements.\n", scalar(keys(%hash)), scalar(@ary); Perl affichera %hash has now 3 keys, @ary 9 elements. Le comportement ci-dessus de local() sur les membres non-existants de types composés est sujet à changements dans le futur. =head2 Passage d'Entrées de Table de Symbole (typeglobs) [Note : le mécanisme décrit dans cette section était à l'origine la seule façon de simuler un passage par référence dans les anciennes versions de Perl. Même si cela fonctionne toujours très bien dans les version modernes, le nouveau mécanisme de référencement est généralement plus facile à utiliser. Voir plus bas.] Parfois, vous ne voulez pas passer la valeur d'un tableau à un sous-programme mais plutôt son nom, pour que le sous-programme puisse modifier sa copie globale plutôt que de travailler sur une copie locale. En perl, vous pouvez vous référer à tous les objets d'un nom particulier en préfixant ce nom par une étoile : C<*foo>. Cela est souvent connu sous le nom de "typeglob", car l'étoile devant peut être conçue comme un caractère générique correspondant à tous les drôles de caractères préfixant les variables et les sous-programmes et le reste. Lorsqu'il est évalué, le typeglob produit une valeur scalaire qui représente tous les objets portant ce nom, y compris tous les handles de fichiers, les formats, ou les sous-programmes. Quand on l'affecte, le nom mentionné se réfère alors à la valeur "C<*>" qui lui a été affectée, quelle qu'elle soit. Exemple : sub doubleary { local(*someary) = @_; foreach $elem (@someary) { $elem *= 2; } } doubleary(*foo); doubleary(*bar); Notez que les scalaires sont déjà passés par référence, vous pouvez donc modifier les arguments scalaires sans utiliser ce mécanisme en vous référant explicitement à C<$_[0]>, etc. Vous pouvez modifier tous les éléments d'un tableau en passant tous les éléments comme des scalaires, mais vous devez utiliser le mécanisme C<*> (ou le mécanisme de référencement équivalent) pour effectuer des C, des C, ou changer la taille d'un tableau. Il sera certainement plus rapide de passer le typeglob (ou la référence). Même si vous ne voulez pas modifier un tableau, ce mécanisme est utile pour passer des tableaux multiples dans une seule LIST, car normalement le mécanisme LIST fusionnera toutes les valeurs de tableaux et vous ne pourrez plus en extraire les tableaux individuels. Pour plus de détails sur les typeglobs, voir L. =head2 Quand faut-il encore utiliser local() Malgré l'existence de C, il y a encore trois endroits où l'opérateur C brille toujours. En fait, en ces trois endroits, vous I utiliser C à la place de C. =over =item 1. Vous avez besoin de donner une valeur temporaire à une variable globale, en particulier C<$_>. Les variables globales, comme C<@ARGV> ou les variables de ponctuation, doivent être Cisées avec C. Ce bloc lit dans F, et le découpe en morceaux, séparés par des lignes de signes égal, qui sont placés dans C<@Fields>. { local @ARGV = ("/etc/motd"); local $/ = undef; local $_ = <>; @Fields = split /^\s*=+\s*$/; } Il est important en particulier de Ciser C<$_> dans toute routine qui l'affecte. Surveillez les affectations implicites dans les conditionnelles C. =item 2. Vous avez besoin de créer un handle de fichier ou de répertoire local, ou une fonction locale. Une fonction ayant besoin de son propre handle de fichier doit utiliser C utilise C sur le typeglob complet (NDT, pas compris la phrase, y'a une gourance ?). Ceci peut être utilisé pour créer de nouvelles entrées dans la table des symboles : sub ioqueue { local (*READER, *WRITER); # pas my ! pipe (READER, WRITER); or die "pipe: $!"; return (*READER, *WRITER); } ($head, $tail) = ioqueue(); Voir le module Symbol pour une façon de créer des entrées de table de symboles anonymes. Puisque l'affectation d'une référence à un typeglob crée un alias, ceci peut être utilisé pour créer ce qui est effectivement une fonction locale, ou au moins un alias local. { local *grow = \&shrink; # seulement jusqu'à la fin de # l'existence de ce bloc grow(); # appelle en fait shrink() move(); # si move() grandit, il rétrécit # aussi } grow(); # récupère le vrai grow() Voir L pour plus de détails sur la manipulation des fonctions par leur nom de cette manière. =item 3. Vous voulez changer temporairement un seul élément d'un tableau ou d'un hachage. Vous pouvez Ciser juste un élément d'un aggrégat. Habituellement, cela est fait dynamiquement : { local $SIG{INT} = 'IGNORE'; funct(); # impossible à interrompre } # la possibilité d'interrompre est restaurée ici Mais cela fonctionne aussi sur les aggrégats déclarés lexicalement. Avant la version 5.005, cette opération pouvait parfois mal se conduire. =back =head2 Passage par Référence Si vous voulez passer plus d'un tableau ou d'un hachage à une fonction -- ou les renvoyer depuis elle -- de façon qu'ils gardent leur intégrité, vous allez devoir alors utiliser un passage par référence explicite. Avant de faire cela, vous avez besoin de comprendre les références telles qu'elles sont détaillées dans L. Cette section n'aura peut-être pas beaucoup de sens pour vous sans cela. Voici quelques exemples simples. Tout d'abord, passons plusieurs tableaux à une fonction puis faisons-lui faire des C sur eux, et retourner une nouvelle liste de tous leurs derniers éléments : @tailings = popmany ( \@a, \@b, \@c, \@d ); sub popmany { my $aref; my @retlist = (); foreach $aref ( @_ ) { push @retlist, pop @$aref; } return @retlist; } Voici comment vous pourriez écrire une fonction retournant une liste des clés apparaissant dans tous les hachages qu'on lui passe : @common = inter( \%foo, \%bar, \%joe ); sub inter { my ($k, $href, %seen); # locals foreach $href (@_) { while ( $k = each %$href ) { $seen{$k}++; } } return grep { $seen{$_} == @_ } keys %seen; } Jusque là, nous utilisons juste le mécanisme normal de retour d'une liste. Que se passe-t-il si vous voulez passer ou retourner un hachage ? Eh bien, si vous n'utilisez que l'un d'entre eux, ou si vous ne voyez pas d'inconvénient à ce qu'ils soient concaténés, alors la convention d'appel normale est valable, même si elle coûte un peu cher. C'est ici que les gens commencent à avoir des problèmes : (@a, @b) = func(@c, @d); ou (%a, %b) = func(%c, %d); Cette syntaxe ne fonctionnera tout simplement pas. Elle définit juste C<@a> ou C<%a> et vide C<@b> ou C<%b>. De plus, la fonction n'a pas obtenu deux tableaux ou hachages séparés : elle a eu une longue liste dans C<@_>, comme toujours. Si vous pouvez vous arranger pour que tout le monde règle cela par des références, cela fait du code plus propre, même s'il n'est pas très joli à regarder (phrase louche, NDT). Voici une fonction qui prend deux références de tableau comme arguments et renvoit les deux éléments de tableau dans l'ordre du nombre d'éléments qu'ils contiennent : ($aref, $bref) = func(\@c, \@d); print "@$aref has more than @$bref\n"; sub func { my ($cref, $dref) = @_; if (@$cref > @$dref) { return ($cref, $dref); } else { return ($dref, $cref); } } Il s'avère en fait que vous pouvez aussi faire ceci : (*a, *b) = func(\@c, \@d); print "@a has more than @b\n"; sub func { local (*c, *d) = @_; if (@c > @d) { return (\@c, \@d); } else { return (\@d, \@c); } } Ici nous utilisons les typeglobs pour faire un aliasing de la table des symboles. C'est un peu subtile, toutefois, et en plus cela ne fonctionnera pas si vous utilisez des variables C, puisque seules les variables globales (et les Ces en fait) sont dans la table des symboles. Si vous passez des handles de fichiers, vous pouvez habituellement juste utiliser le typeglob tout seul, comme C<*STDOUT>, mais les références de typeglobs seraient meilleures car elle fonctionneront toujours correctement sous S>. Par exemple : splutter(\*STDOUT); sub splutter { my $fh = shift; print $fh "her um well a hmmm\n"; } $rec = get_rec(\*STDIN); sub get_rec { my $fh = shift; return scalar <$fh>; } Une autre façon de faire cela est d'utiliser C<*HANDLE{IO}>, voir L pour son usage et ses pièges. Si vous comptez générer de nouveau handles de fichiers, vous pourriez faire ceci : sub openit { my $name = shift; local *FH; return open (FH, $path) ? *FH : undef; } Bien que cela produire en fait une petite fuite de mémoire. Voir la fin de L pour une façon un peu plus propre d'utiliser le paquetage C. =head2 Prototypes Avec la version 5.002 de perl, si vous déclarez sub mypush (\@@) alors C prendra ses arguments exactement comme C le fait. La declaration de la fonction qui doit être appelée doit être visible au moment de la compilation. Le prototype affecte seulement l'interprétation des appels nouveau style de la fonction, où le nouveau style est défini comme n'utilisant pas le caractère C<&>. En d'autres termes, si vous l'appelez comme une fonction intégrée, alors elle se comportera comme une fonction intégrée. Si vous l'appelez comme un sous-programme à l'ancienne mode, alors elle se comportera comme un sous-programme à l'ancienne. La conséquence naturelle de cette règle est que les prototypes n'ont pas d'influence sur les références de sous-programmes comme C<\&foo> ou sur les appels de sous-programmes indirects comme C<&{$subref}> ou C<$subref-E()>. Les appels de méthode ne sont pas non plus influencés par les prototypes, car la fonction qui doit être appelée est indéterminée au moment de la compilation, puisqu'elle dépend de l'héritage. Puisque l'intention primitive est de vous laisser définir des sous-programmes qui fonctionnent comme des commandes intégrées, voici des prototypes pour quelques autres fonctions qui se compilent presque exactement comme les fonctions intégrées correspondantes. Déclarées en tant que Appelé comme sub mylink ($$) mylink $old, $new sub myvec ($$$) myvec $var, $offset, 1 sub myindex ($$;$) myindex &getstring, "substr" sub mysyswrite ($$$;$) mysyswrite $buf, 0, length($buf) - $off, $off sub myreverse (@) myreverse $a, $b, $c sub myjoin ($@) myjoin ":", $a, $b, $c sub mypop (\@) mypop @array sub mysplice (\@$$@) mysplice @array, @array, 0, @pushme sub mykeys (\%) mykeys %{$hashref} sub myopen (*;$) myopen HANDLE, $name sub mypipe (**) mypipe READHANDLE, WRITEHANDLE sub mygrep (&@) mygrep { /foo/ } $a, $b, $c sub myrand ($) myrand 42 sub mytime () mytime Tout caractère de prototype précédé d'une barre oblique inverse représente un véritable argument qui doit absolument commencer par ce caractère. La valeur passée au sous-programme (contenue dans C<@_>) sera une référence au véritable argument donné dans l'appel du sous-programme, obtenue en appliquant C<\> à cet argument. Les caractères de prototype non précédés d'une barre oblique inverse ont une signification spéciale. Tout C<@> ou C<%> sans barre oblique inverse mange tout le reste des arguments, et force un contexte de liste. Un argument représenté par C<$> force un contexte scalaire. Un C<&> requiert un sous-programme anonyme, qui, s'il est passé comme premier argument, ne requiert pas le mot-clé "C" ni une virgule après lui. Un C<*> permet au sous-programme d'accepter un bareword, une constante, une expression scalaire, un typeglob, ou une référence à un typeglob à cet emplacement. La valeur sera disponible pour le sous-programme soit comme un simple scalaire, soit (dans les deux derniers cas) comme une référence au typeglob. Un point-virgule sépare les arguments obligatoires des arguments optionnels (il est redondant devant C<@> ou C<%>). Notez comment les trois derniers exemples ci-dessus sont traités spécialement par l'analyseur. C est compilé comme un véritable opérateur de liste, C comme un véritable opérateur unaire avec une précédence unaire identique à celle de C, et C est vraiment sans arguments, tout comme C. C'est-à-dire que si vous dites mytime +2; Vous obtiendrez C, et pas C, qui est la façon dont cela serait analysé sans le prototype. La chose intéressante à propos de C<&> est que vous pouvez générer une nouvelle syntaxe grâce à lui : sub try (&@) { my($try,$catch) = @_; eval { &$try }; if ($@) { local $_ = $@; &$catch; } } sub catch (&) { $_[0] } try { die "phooey"; } catch { /phooey/ and print "unphooey\n"; }; Cela affiche C<"unphooey"> (Oui, il y a toujours des problèmes non résolus à propos de la visibilité de C<@_>. J'ignore cette question pour le moment (Mais notez que si nous donnons une portée lexicale à C<@_>, ces sous-programmes anonymes peuvent agir comme des fermetures... (Mince, est-ce que ceci sonne un peu lispien ? (Peu importe))). Et voici une réimplémentation de C : sub mygrep (&@) { my $code = shift; my @result; foreach $_ (@_) { push(@result, $_) if &$code; } @result; } Certaines gens préféreraient des prototypes pleinement alphanumériques. Les caractères alphanumériques ont intentionnellement été laissés hors des prototypes expressément dans le but d'ajouter un jour futur des paremètres formels nommés. Le principal objectif du mécanisme actuel est de laisser les programmeurs de modules fournir de meilleurs diagnostics à leurs utilisateurs. Larry estime que la notation est bien compréhensible pour les programmeurs Perl, et que cela n'interfèrera pas notablement avec le coeur du module, ni ne le rendra plus difficile à lire. Le bruit sur la ligne est visuellement encapsulé dans une petite pilule facile à avaler. Il est probablement meilleur de prototyper les nouvelles fonctions, et de ne pas prototyper rétrospectivement les anciennes. C'est parce que vous devez être particulièrement précautionneux avec les exigences silencieuses de la différence entre les contextes de liste et les contextes scalaires. Par exemple, si vous décidez qu'une fonction devrait prendre juste un paramètre, comme ceci : sub func ($) { my $n = shift; print "you gave me $n\n"; } et que quelqu'un l'a appelée avec un tableau ou une expression retournant une liste : func(@foo); func( split /:/ ); Alors vous venez juste de fournir un C automatique devant leurs arguments, ce qui peut être plus que surprenant. L'ancien C<@foo> qui avait l'habitude de ne contenir qu'une chose n'entre plus. À la place, le C se voit maintenant passer C<1>, soit le nombre d'éléments dans C<@foo>. Et le C se voit appeler dans un contexte scalaire et commence à gribouiller dans votre liste de paramètres C<@_>. Tout ceci est très puissant, bien sûr, et devrait être utilisé uniquement avec modération pour rendre le monde meilleur. =head2 Fonctions Constantes Les fonctions ayant un prototype égal à C<()> sont des candidates potentielles à l'insertion en ligne (inlining, NDT). Si le résultat après optimisation et repliement des constantes est soit une constante soir un scalaire de portée lexicale n'ayant pas d'autre référence, alors il sera utilisé à la place des appels à la fonction faits sans C<&> ou C. Les appels réalisés en utilisant C<&> ou C ne sont jamais insérés en ligne (Voir F pour une façon aisée de déclarer la plupart des constantes). Les fonctions suivantes seraient toutes insérées en ligne : sub pi () { 3.14159 } # Pas exact, mais proche. sub PI () { 4 * atan2 1, 1 } # Aussi exact qu'il # puisse être, et # inséré en ligne aussi ! sub ST_DEV () { 0 } sub ST_INO () { 1 } sub FLAG_FOO () { 1 << 8 } sub FLAG_BAR () { 1 << 9 } sub FLAG_MASK () { FLAG_FOO | FLAG_BAR } sub OPT_BAZ () { not (0x1B58 & FLAG_MASK) } sub BAZ_VAL () { if (OPT_BAZ) { return 23; } else { return 42; } } sub N () { int(BAZ_VAL) / 3 } BEGIN { my $prod = 1; for (1..N) { $prod *= $_ } sub N_FACTORIAL () { $prod } } Si vous redéfinissez un sous-programmes qui pouvait être inséré en ligne, vous obtiendrez un avertissement formel (vous pouvez utiliser cet avertissement pour déterminer si un sous-programme particulier est considéré comme constant ou pas). L'avertissement est considéré comme suffisamment sévère pour ne pas être optionnel, car les invocations précédemment compilées de la fonction utiliseront toujours l'ancienne valeur de cette fonction. Si vous avez besoin de pouvoir redéfinir le sous-programme, vous devez vous assurer qu'il n'est pas inséré en ligne, soit en abandonnant le prototype C<()> (ce qui change la sémantique de l'appel, donc prenez garde), soit en contrecarrant le mécanisme d'insertion d'une autre façon, comme par exemple sub not_inlined () { 23 if $]; } =head2 Surcharges des Fonctions Prédéfinies Beaucoup de fonctions prédéfinies peuvent être surchargées, même si cela ne devrait être essayé qu'occasionnellement et pour une bonne raison. Typiquement, cela pourrait être réalisé par un paquetage essayant d'émuler une fonctionnalité prédéfinie manquante sur un système non Unix. La surcharge ne peut être réalisée qu'en important le nom depuis un module -- la prédéclaration ordinaire n'est pas suffisante. Toutefois, le pragma C (directive du compilateyr) vous laisse, dans les faits, prédéclarer les sous-programmes via la syntaxe d'importation, et ces noms peuvent ensuite surcharger ceux qui sont prédéfinis : use subs 'chdir', 'chroot', 'chmod', 'chown'; chdir $somewhere; sub chdir { ... } Pour se référer sans ambiguïté à la forme prédéfinie, on peut faire précéder le nom prédéfini par le qualificateur de paquetage spéciale C. Par exemple, le fait de dire C se référera toujours à la fonction prédéfinie C, même si le paquetage courant a importé d'ailleurs un quelconque autre sous-programme appelé C<&open()>. Les modules de bibliothèque ne devraient en général pas exporter de noms prédéfinis comme "C" ou "C" comme partie de leur liste C<@EXPORT> par défaut, car ceux-ci pourraient s'infiltrer dans l'espace de noms de quelqu'un d'autre et changer la sémantique de façon inattendue. À la place, si le module ajoute le nom à la liste C<@EXPORT_OK>, alors il est possible pour un utilisateur d'importer le nom explicitement, mais pas implicitement. C'est-à-dire qu'il pourrait dire use Module 'open'; et cela importerait la surcharge C, mais s'il disait use Module; il obtiendrait les importations par défaut sans les surcharges. Le mécanisme précédent de surcharge des éléments prédéfinis est restreint, assez délibérément, au paquetage qui réclame l'importation. Il existe une seconde méthode parfois applicable lorsque vous désirez surcharger partout une fonction prédéfinie, sans tenir compte des frontières entre espaces de noms. Cela s'obtient en important un sous-programme dans l'espace de noms spécial C. Voici un exemple qui remplace assez effrontément l'opérateur C par quelque chose qui comprend les expressions rationnelles. package REGlob; require Exporter; @ISA = 'Exporter'; @EXPORT_OK = 'glob'; sub import { my $pkg = shift; return unless @_; my $sym = shift; my $where = ($sym =~ s/^GLOBAL_// ? 'CORE::GLOBAL' : caller(0)); $pkg->export($where, $sym, @_); } sub glob { my $pat = shift; my @got; local(*D); if (opendir D, '.') { @got = grep /$pat/, readdir D; closedir D; } @got; } 1; Et voici comment on pourrait en (ab)user : #use REGlob 'GLOBAL_glob'; # surcharge glob() dans TOUS les # espaces de noms package Foo; use REGlob 'glob'; # surcharge glob() dans Foo:: # seulement print for <^[a-z_]+\.pm\$>; # montre tous les modules pragmatiques Notez que le commentaire initial montre un exemple artificiel, voire même dangereux. En surchargeant C globalement, vous forceriez le nouveau (et subversif) comportement de l'opérateur C pour B les espaces de noms, sans la complète coopération des modules qui possèdent ces espaces de noms, et sans qu'ils en aient même connaissance. Naturellement, ceci doit être fait avec d'extrêmes précautions -- si jamais cela doit être fait. L'exemple C ci-dessus n'implémente pas tous le support nécessaires pour surcharger proprement l'opérateur C de perl. La fonction intégrée C a des comportements différents selon qu'elle apparaît dans un contexte scalaire ou un contexte de lites, mais ce n'est pas le cas de notre C. En fait, beaucoup de fonctions prédéfinies de perl ont de tels comportements sensibles au contexte, et ceux-ci doivent être supportés de façon adéquate par une surcharge correctement écrite. Pour un exemple pleinement fonctionnel de surcharge de C, étudiez l'implémentation de C dans la bibliothèque standard. =head2 Autochargement Si vous appelez un sous-programme indéfini, vous obtenez ordinairement une erreur fatale immédiatement se plaignant que le sous-programme n'existe pas (De même pour les sous-programmes utilisés comme méthodes, lorsque la méthode n'existe dans aucune classe de base du paquetage de classe). Si, toutefois, il existe un sous-programme C défini dans le paquetage ou dans les paquetages ayant été explorés pour le sous-programme originel, alors ce sous-programme C est appelé avec les arguments qui auraient été passés au sous-programme originel. Le nom pleinement qualifié du sous-programme originel apparaît magiquement dans la variable C<$AUTOLOAD> dans le même paquetage que la routine C. Le nom n'est pas passé comme un argument ordinaire parce que, euh, eh bien, juste parce que, c'est pour ça... La plupart des routines C chargeront une définition du sous-programme en question en utilisant eval, puis l'exécuteront en utilisant une forme spéciale de "goto" qui efface de la pile sans laisser de traces la routine C (Voir le module standard C pour un exemple). Mais une routine C peut aussi juste émuler la routine et ne jamais la définir. Par exemple, supposons qu'une fonction non encore définie doive juste appeler C avec ces arguments. Tout ce que vous feriez est ceci : sub AUTOLOAD { my $program = $AUTOLOAD; $program =~ s/.*:://; system($program, @_); } date(); who('am', 'i'); ls('-l'); En fait, si vous prédéclarez les fonctions que vous désirez appeler de cette façon, vous n'avez mêmes pas besoin des parenthèses : use subs qw(date who ls); date; who "am", "i"; ls -l; Un exemple plus complet de ceci est le module Shell standard, qui peut traiter des appels indéfinis à des sous-programmes comme des appels de programmes Unix. Des mécanismes sont disponibles pour les auteurs de modules afin de les aider à découper les modules en fichiers autochargeables. Voir le module standard AutoLoader décrit dans L et dans L, les modules standards SelfLoader dans L, et le document expliquant comment ajouter des fonctions C au code perl dans L. =head1 VOIR AUSSI Voir L pour plus de détails sur les références et les fermetures. Voir L si vous aimeriez apprendre comment appeler des sous-programmes en C depuis perl. Voir L pour apprendre à emballer vos fonctions dans des fichiers séparés. =head1 TRADUCTION =head2 Version Cette traduction française correspond à la version anglaise distribuée avec perl 5.005_02. Pour en savoir plus concernant ces traductions, consultez L. =head2 Traducteur Roland Trique >