En quoi $ _ est-il différent des arguments d'entrée ou de boucle nommés?
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.
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.