Question

Je suis en train de voir que les deux sont utilisés dans ce script et que la documentation n’est pas claire. Quelqu'un peut-il démystifier cela pour moi?

Était-ce utile?

La solution

Portée dynamique. C'est un concept soigné. Beaucoup de gens ne l'utilisent pas ou ne le comprennent pas.

En gros, pensez à my comme créant et ancrant une variable à un bloc de {}, A.K.A. portée.

my $foo if (true); # $foo lives and dies within the if statement.

Donc, une variable my est ce à quoi vous êtes habitué. alors qu'avec la portée dynamique, $ var peut être déclaré n'importe où et utilisé n'importe où. Donc, avec local , vous suspendez fondamentalement l'utilisation de cette variable globale et utilisez une "valeur locale". travailler avec elle. Donc, local crée une portée temporaire pour une variable temporaire.

$var = 4;
print $var, "\n";
&hello;
print $var, "\n";

# subroutines
sub hello {
     local $var = 10;
     print $var, "\n";
     &gogo; # calling subroutine gogo
     print $var, "\n";
}
sub gogo {
     $var ++;
}

Ceci devrait imprimer:

4
10
11
4

Autres conseils

La réponse courte est que my marque une variable comme privée dans une étendue lexicale et que local marque une variable comme privée dans une étendue dynamique.

Il est plus facile de comprendre mon , car cela crée une variable locale au sens habituel. Une nouvelle variable a été créée et elle n’est accessible que dans le bloc lexical englobant, qui est généralement indiqué par des accolades. Il existe quelques exceptions à la règle d'accolade, telles que:

foreach my $x (@foo) { print "$x\n"; }

Mais ce n'est que Perl qui fait ce que vous voulez dire. Normalement, vous avez quelque chose comme ça:

sub Foo {
   my $x = shift;

   print "$x\n";
}

Dans ce cas, $ x est privé du sous-programme et son étendue est entourée par des accolades. La chose à noter, et ceci contraste avec local , est que la portée d'une variable my est définie par rapport à votre code tel qu'il est écrit dans le fichier. C'est un phénomène de compilation.

Pour comprendre local , vous devez penser à la pile d'appels de votre programme en cours d'exécution. Lorsqu'une variable est local , elle est redéfinie à partir du point où l'instruction local est exécutée pour tout ce qui se trouve en dessous de la pile, jusqu'à ce que vous retourniez dans la pile pour l'appelant. du bloc contenant le local .

Cela peut être déroutant au début, alors considérez l'exemple suivant.

sub foo { print "$x\n"; }
sub bar { local $x; $x = 2; foo(); }

$x = 1;
foo(); # prints '1'
bar(); # prints '2' because $x was localed in bar
foo(); # prints '1' again because local from foo is no longer in effect

Lorsque toto est appelé pour la première fois, il voit la valeur globale de $ x , qui est 1. Lorsque bar est appelé et < code> local $ x s'exécute, ce qui redéfinit le $ x global de la pile. Désormais, lorsque toto est appelé depuis la barre , il voit la nouvelle valeur 2 pour $ x . Jusqu'ici, ce n'est pas très spécial, car la même chose se serait produite sans l'appel à local . La magie est que lorsque bar renvoie, nous quittons la portée dynamique créée par local $ x et le précédent $ x global revient dans la portée. Donc, pour le dernier appel de foo , $ x est égal à 1.

Vous voudrez presque toujours utiliser mon , car cela vous donne la variable locale que vous recherchez. Une fois dans une lune bleue, local est vraiment pratique pour faire des choses cool.

Citant Apprentissage Perl :

  

Mais local est mal nommé, ou du moins mal nommé. Notre ami Chip Salzenberg dit que s’il avait la chance de revenir en 1986 dans une machine à remonter le temps et de donner un conseil à Larry, il demanderait à Larry d’appeler le local par le nom "save". au lieu de cela. [14] En effet, local économisera la valeur de la variable globale donnée et sera ensuite automatiquement restaurée dans la variable globale. (C’est vrai: ces variables dites "locales" sont en réalité des globals!) Ce mécanisme de sauvegarde et de restauration est identique à celui que nous avons déjà vu deux fois maintenant, dans la variable de contrôle d’une boucle foreach et dans le @ _ tableau de paramètres de sous-programme.

Ainsi, local enregistre la valeur actuelle d'une variable globale, puis la définit sous une forme de valeur vide. Vous le verrez souvent utilisé pour insuffler un fichier entier au lieu de juste une ligne:

my $file_content;
{
    local $/;
    open IN, "foo.txt";
    $file_content = <IN>;
} 

L'appel de local $ / définit le séparateur d'enregistrement d'entrée (la valeur selon laquelle Perl arrête de lire une "ligne" at) sur une valeur vide, obligeant l'opérateur du vaisseau spatial à lire le fichier entier. ne frappe jamais le séparateur d'enregistrement d'entrée.

Je ne peux pas croire que personne n’a fait le lien avec les traités exhaustifs de Mark Jason Dominus sur le sujet:

http://perldoc.perl.org/perlsub .html # Variables-privées-via-mon ()

  

Contrairement aux variables dynamiques créées par   l'opérateur local, variables lexicales   déclaré avec mon sont totalement cachés   du monde extérieur, y compris tout   appelé sous-routines. Ceci est vrai si   c'est le même sous-programme appelé de   lui-même ou ailleurs - chaque appel reçoit   sa propre copie.

http://perldoc.perl.org/perlsub .html # Temporary-Values-via-local ()

  

Un local modifie ses variables listées   être " local " au bloc englobant,   eval, ou faire FILE - et à tout   sous-programme appelé de l'intérieur de cette   bloc. Un local donne juste temporaire   valeurs en global (ce qui signifie paquet)   variables. Il ne crée pas de local   variable. Ceci est connu comme dynamique   cadrage. Le cadrage lexical se fait avec   mon, qui fonctionne plus comme l'auto de C   déclarations.

Je ne pense pas que cela soit du tout obscur, sauf que de dire que par "local au bloc englobant", cela veut dire que la valeur d'origine est restaurée à la sortie du bloc.

Eh bien, Google travaille vraiment pour vous sur celui-ci: http://www.perlmonks.org/? node_id = 94007

À partir du lien:

  

Résumé rapide: "mon" crée un nouveau   variable, 'local' modifie temporairement   la valeur d'une variable.

     

c'est-à-dire, 'local' modifie temporairement la   valeur de la variable , mais seulement    dans la portée dans laquelle il existe.

Utilisez généralement mon, c'est plus rapide et ne fait rien de bizarre.

À partir de man perlsub :

Contrairement aux variables dynamiques créées par l'opérateur local, les variables lexicales déclarées avec my sont totalement masquées du monde extérieur, y compris des sous-routines appelées.

Ainsi, par simplification excessive, mon rend votre variable visible uniquement là où elle est déclarée. local le rend également visible dans la pile d'appels. Vous voudrez généralement utiliser my au lieu de local .

Votre confusion est compréhensible. Le cadrage lexical est assez facile à comprendre mais le cadrage dynamique est un concept inhabituel. La situation est aggravée par les noms my et local étant quelque peu imprécis (ou du moins peu intuitifs) pour des raisons historiques.

my déclare une variable lexicale, visible depuis le point de déclaration jusqu'à la fin du bloc (ou fichier) englobant. Elle est complètement indépendante de toute autre variable du même nom dans le reste du programme. C'est privé à ce bloc.

local , en revanche, déclare une modification temporaire de la valeur d'une variable globale. Le changement se termine à la fin de la portée englobante, mais la variable - étant globale - est visible n’importe où dans le programme.

En règle générale, utilisez my pour déclarer vos propres variables et local pour contrôler l'impact des modifications apportées aux variables intégrées de Perl.

Pour une description plus détaillée, voir l'article de Mark Jason Dominus Faire face au cadrage .

local est une méthode de localisation plus ancienne, à l'époque où Perl n'avait qu'une portée dynamique. Le cadrage lexical est beaucoup plus naturel pour le programmeur et beaucoup plus sûr dans de nombreuses situations. mes variables appartiennent à la portée (bloc, package ou fichier) dans laquelle elles sont déclarées.

Les variables locales appartiennent à la place à un espace de noms global. Si vous faites référence à une variable $ x avec local, vous faites en réalité référence à $ main :: x, qui est une variable globale. Contrairement à ce que son nom l'indique, toute action locale consiste à insérer une nouvelle valeur dans une pile de valeurs pour $ main :: x jusqu'à la fin de ce bloc, auquel cas l'ancienne valeur sera restaurée. C’est une fonctionnalité utile en soi, mais ce n’est pas un bon moyen d’avoir des variables locales pour une foule de raisons (pensez ce qui se passe quand vous avez des threads! vous avez localisé!). Cependant, c’était la seule façon d’avoir des variables qui ressemblaient à des variables locales à l’époque antérieure à Perl 5. Nous sommes toujours bloqués.

"mon" les variables ne sont visibles que dans le bloc de code actuel. " local " les variables sont également visibles partout où elles étaient visibles auparavant. Par exemple, si vous dites "mon $ x;" et appeler une sous-fonction, il ne peut pas voir cette variable $ x. Mais si vous dites "local $ /;" (pour annuler la valeur du séparateur d'enregistrement), vous modifiez le mode de lecture des fichiers dans les fonctions que vous appelez.

En pratique, vous voulez presque toujours "mon", pas "local".

Regardez le code suivant et sa sortie pour comprendre la différence.

our $name = "Abhishek";

sub sub1
{
    print "\nName = $name\n";
    local $name = "Abhijeet";

    &sub2;
    &sub3;
}

sub sub2
{
    print "\nName = $name\n";
}

sub sub3
{
    my $name = "Abhinav";
    print "\nName = $name\n";
}


&sub1;

La sortie est:

Name = Abhishek

Name = Abhijeet

Name = Abhinav

L'exemple de dinomite consistant à utiliser local pour redéfinir le séparateur d'enregistrement est la seule fois que j'ai rencontré beaucoup de programmes Perl. Je vis dans un environnement de niche en Perl [programmation de sécurité], mais mon domaine de compétence est rarement utilisé.

&s;

sub s()
{
    local $s="5";
    &b;
    print $s;
}

sub b()
{
    $s++;
}

Le script ci-dessus imprime 6.

Mais si nous changeons de local en mon message 5 sera imprimé.

C'est la différence. Simple.

Je pense que la meilleure façon de s'en souvenir est la suivante. MY crée une nouvelle variable. LOCAL modifie temporairement la valeur d'une variable existante.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top