En quoi $ _ est-il différent des arguments d'entrée ou de boucle nommés?

StackOverflow https://stackoverflow.com/questions/5405423

  •  29-10-2019
  •  | 
  •  

Question

Comme j'utilise $ _ beaucoup, je veux mieux comprendre son utilisation. $ _ est une variable globale pour les valeurs implicites pour autant que je comprenne et que je l'ai utilisée.

Comme $ _ semble être réglé de toute façon, y a-t-il des raisons d'utiliser des variables de boucle nommées sur $ _ outre lisibilité?

Dans quels cas cela importe-t-il $ _ une variable globale est-elle?

Donc si j'utilise

for (@array){
    print $_;
}

ou même

print $_ for @array;

il a le même effet que

for my $var (@array){
    print $var;
}

Mais cela fonctionne-t-il de la même manière? Je suppose que ce n'est pas exactement mais quelles sont les différences réelles?

Mise à jour:

Il semble que $ _ soit même correctement coté dans cet exemple. N'est-ce plus mondial? J'utilise 5.12.3.

#!/usr/bin/perl
use strict;
use warnings;

my @array = qw/one two three four/;
my @other_array = qw/1 2 3 4/;

for (@array){
    for (@other_array){
        print $_;
    }
    print $_;
}

qui imprime correctement 1234one1234TWO1234THREE1234Four.

Pour Global $ _, je m'attendais à 1234 4 1234 4 1234 4 1234 4 .. ou est-ce que je manque quelque chose d'évident?

Quand $ _ Global est-il alors?

Mise à jour:

OK, après avoir lu les différentes réponses et Perlsynyn plus attentivement, je suis arrivé à une conclusion:

Outre la lisibilité, il est préférable d'éviter d'utiliser $ _ car la localisation implicite de $ _ doit être connue et prise en compte, sinon on pourrait rencontrer un comportement inattendu.

Merci pour la clarification de cette question.

Était-ce utile?

La solution

are there reasons to use named loop variables over $_ besides readability?

Le problème n'est pas s'ils sont nommés ou non. Le problème est s'ils sont des «variables de package» ou des «variables lexicales».

Voir la très bonne description des 2 systèmes de variables utilisés dans Perl "Faire face à la portée":

http://perl.plover.com/faqs/namespaces.html

Les variables de package sont des variables globales et doivent donc être évitées pour toutes les raisons habituelles (par exemple, l'action à distance).

Éviter les variables de package est une question de "fonctionnement correct" ou "plus difficile d'injecter des bogues" plutôt qu'une question de "lisibilité".

In what cases does it matter $_ is a global variable?

Partout.

La meilleure question est:

In what cases is $_ local()ized for me?

Il y a quelques endroits où Perl sera local () ize $ _ pour vous, principalement foreach, grep et map. Tous les autres endroits exigent que vous vous localisez vous-même. :-)

Autres conseils

Le mode de défaillance classique de l'utilisation $_ (implicitement ou explicitement) comme une variable de boucle est

for $_ (@myarray) {
  /(\d+)/ or die;
  foo($1);
}

sub foo {
  open(F, "foo_$_[0]") or die;
  while (<F>) {
    ...
  }
}

où, parce que la variable de boucle dans for/foreach est lié à l'élément de liste réel, signifie que le while (<F>) écraser @myarray avec des lignes lues à partir des fichiers.

$ _ est le même que de nommer la variable que dans votre deuxième exemple avec la façon dont il est généralement utilisé. $ _ n'est qu'un nom de variable par défaut de raccourci pour l'élément actuel dans la boucle actuelle pour économiser sur la saisie lors d'une boucle rapide et simple. J'ai tendance à utiliser des variables nommées plutôt que la valeur par défaut. Cela montre plus clairement ce que c'est et si je dois faire une boucle imbriquée, il n'y a pas de conflits.

Étant donné que $ _ est une variable globale, vous pouvez obtenir des valeurs inattendues si vous essayez d'utiliser sa valeur qu'elle avait à partir d'un bloc de code précédent. Le nouveau bloc de code peut faire partie d'une boucle ou d'une autre opération qui insère ses propres valeurs en $ _, écrasant ce que vous attendiez.

Le risque d'utiliser $ _ est qu'il est global (sauf si vous le localisez avec local $_), et donc si une fonction que vous appelez dans votre boucle utilise également $ _, les deux utilisations peuvent interférer.

Pour des raisons qui ne sont pas claires pour moi, cela ne m'a mordu que de temps en temps, mais je localise généralement $ _ si je l'utilise à l'intérieur des packages.

Il n'y a rien de spécial dans $_ En dehors de cela, le paramètre par défaut pour de nombreuses fonctions. Si vous élaborez explicitement lexicalement votre $_ avec my, Perl utilisera la version locale de $_ plutôt que le monde. Il n'y a rien d'étrange, c'est comme n'importe quelle autre variable nommée.

sub p { print "[$_]"; } # Prints the global $_
# Compare and contrast
for my $_ (b1..b5) { for my $_ (a1..a5) { p } } print "\n"; # ex1
for my $_ (b1..b5) { for       (a1..a5) { p } } print "\n"; # ex2
for       (b1..b5) { for my $_ (a1..a5) { p } } print "\n"; # ex3
for       (b1..b5) { for       (a1..a5) { p } } print "\n"; # ex4

Vous devriez être légèrement mystifié par la sortie jusqu'à ce que vous découvriez que Perl préservera la valeur d'origine de la variable de boucle à la sortie de la boucle (voir perlsyn).

Noter ex2 au dessus. Ici, la deuxième boucle utilise la portée lexicalement $_ déclaré dans la première boucle. Subtil, mais attendu. Encore une fois, cette valeur est conservée à la sortie afin que les deux boucles ne pas interférer.

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