質問
$_ をよく使うので、その使い方をもっと理解したいと思っています。$_ は、私が理解して使用した限り、暗黙的な値のグローバル変数です。
とにかく $_ が設定されているようですが、$_ に対して名前付きループ変数を使用する理由はありますか? その上 読みやすさ?
$_ がグローバル変数であることが重要になるのはどのような場合ですか?
だから私が使うなら
for (@array){
print $_;
}
あるいは
print $_ for @array;
それと同じ効果があります
for my $var (@array){
print $var;
}
しかし、それは同じように機能しますか?正確には違うと思いますが、実際の違いは何ですか?
アップデート:
この例では $_ のスコープも正しく設定されているようです。もうグローバルではないのでしょうか?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 $_;
}
1234one1234two1234three1234four が正しく表示されます。
グローバル $_ の場合は 1234 を予想していました 4 1234 4 1234 4 1234 4 ..それとも何か明らかなことが欠けているのでしょうか?
$_ がグローバルになるのはいつですか?
アップデート:
OK、さまざまな回答と perlsyn をより注意深く読んだ後、次の結論に達しました。
読みやすさに加えて、$_ の暗黙的なローカリゼーションを認識して考慮する必要があるため、$_ の使用は避けた方がよいでしょう。そうしないと、予期しない動作が発生する可能性があります。
その件について説明していただきありがとうございます。
解決
問題は、名前が付けられているかどうかではありません。問題は、それらが「パッケージ変数」または「字句変数」であるかどうかです。
Perlの「CopingwithScoping」で使用される2つの変数システムの非常に優れた説明を参照してください:
http://perl.plover.com/FAQs/Namespaces.html
パッケージ変数はグローバル変数であるため、通常の理由(遠隔作用など)では避ける必要があります。
パッケージ変数の回避は、「読みやすさ」の問題ではなく、「正しい操作」または「バグの挿入が難しい」の問題です。 ジェネラコディセタグプレ
どこでも。
より良い質問は次のとおりです: ジェネラコディセタグプレ
Perlが$ _をlocal()化する場所がいくつかあります。主にforeach、grep、mapです。他のすべての場所では、自分でlocal()化する必要があるため、必然的にそうすることを忘れると、潜在的なバグが発生します。:-)
他のヒント
を使用した場合の古典的な障害モード $_
(暗黙的または明示的に) ループ変数として
for $_ (@myarray) {
/(\d+)/ or die;
foo($1);
}
sub foo {
open(F, "foo_$_[0]") or die;
while (<F>) {
...
}
}
ここで、ループ変数は for
/foreach
実際のリスト項目にバインドされているということは、 while (<F>)
上書きします @myarray
ファイルから読み取られた行を含む。
$ _は、2番目の例のように、通常使用される方法で変数に名前を付けるのと同じです。$ _は、現在のループ内の現在のアイテムのショートカットのデフォルト変数名であり、すばやく簡単なループを実行するときに入力を節約できます。私はデフォルトではなく名前付き変数を使用する傾向があります。それが何であるかがより明確になり、ネストされたループを実行する必要が生じた場合でも、競合は発生しません。
$ _はグローバル変数であるため、前のコードブロックから取得した値を使用しようとすると、予期しない値が取得される可能性があります。新しいコードブロックは、独自の値を$ _に挿入し、そこにあると予想されていたものを上書きするループまたはその他の操作の一部である可能性があります。
$ _を使用する場合のリスクは、グローバルであるため(local $_
でローカライズしない限り)、ループで呼び出す関数が$ _も使用する場合、2つの使用が干渉する可能性があります。
理由がはっきりしないので、これはたまにしか噛みませんが、パッケージ内で使用する場合は通常$ _をローカライズします。
$_
は、多くの関数のデフォルトパラメータであることを除けば、特別なことは何もありません。明示的に$_
をmy
で字句スコープする場合、perlはグローバルバージョンではなくローカルバージョンの$_
を使用します。これには何も奇妙なことはありません。他の名前付き変数とまったく同じです。
ジェネラコディセタグプレ
perlがループ終了時にループ変数の元の値を保持することがわかるまで、出力に少し不思議に思うはずです( perlsyn を参照)。
上記の ex2 に注意してください。ここで、2番目のループは、最初のループで宣言された字句スコープの$_
を使用しています。微妙ですが、期待されています。この場合も、この値は終了時に保持されるため、2つのループが干渉することはありません。