$_ は名前付き入力引数やループ引数とどう違うのですか?

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

  •  29-10-2019
  •  | 
  •  

質問

$_ をよく使うので、その使い方をもっと理解したいと思っています。$_ は、私が理解して使用した限り、暗黙的な値のグローバル変数です。

とにかく $_ が設定されているようですが、$_ に対して名前付きループ変数を使用する理由はありますか? その上 読みやすさ?

$_ がグローバル変数であることが重要になるのはどのような場合ですか?

だから私が使うなら

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つのループが干渉することはありません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top