3

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

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

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

だから私が使うなら

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 ..を期待していましたか、それとも明らかな何かが欠けていますか?

$ _グローバルはいつですか?

更新

さて、さまざまな答えとperlsynをもっと注意深く読んだ後、私は結論に達しました:

読みやすさに加えて、$ _の暗黙的なローカリゼーションを知って考慮に入れる必要があるため、$ _の使用を避けることをお勧めします。そうしないと、予期しない動作が発生する可能性があります。

その問題を明確にしてくれてありがとう。

4

5 に答える 5

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

問題は、名前が付けられているかどうかではありません。問題は、それらが「パッケージ変数」または「字句変数」であるかどうかです。

Perlの「スコープによる対処」で使用される2つの変数システムの非常に優れた説明を参照してください。

http://perl.plover.com/FAQs/Namespaces.html

パッケージ変数はグローバル変数であるため、通常の理由(遠隔作用など)では避ける必要があります。

パッケージ変数の回避は、「読みやすさ」の問題ではなく、「正しい操作」または「バグの挿入が難しい」の問題です。

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

どこにでも。

より良い質問は次のとおりです。

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

Perlが$_をlocal()化する場所がいくつかあります。主にforeach、grep、mapです。他のすべての場所では、自分でlocal()化する必要があるため、必然的にそうすることを忘れると、潜在的なバグが発生します。:-)

于 2011-03-23T14:13:17.493 に答える
8

$_ループ変数として(暗黙的または明示的に)使用する古典的な故障モードは次のとおりです。

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

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

forここで、 /のループ変数foreachは実際のリストアイテムにバインドされているため、ファイルから読み取られた行でwhile (<F>)上書きされることを意味します。@myarray

于 2011-03-23T12:52:32.643 に答える
3

$ _は、2番目の例のように、通常使用される方法で変数に名前を付けるのと同じです。$ _は、現在のループ内の現在のアイテムのショートカットのデフォルト変数名であり、すばやく簡単なループを実行するときに入力を節約できます。私はデフォルトではなく名前付き変数を使用する傾向があります。それが何であるかをより明確にし、ネストされたループを実行する必要が生じた場合でも、競合は発生しません。

$ _はグローバル変数であるため、前のコードブロックからの値を使用しようとすると、予期しない値が取得される可能性があります。新しいコードブロックは、ループまたはその他の操作の一部である可能性があり、独自の値を$ _に挿入して、そこにあると予想されるものを上書きします。

于 2011-03-23T12:47:13.690 に答える
2

$ _を使用する場合のリスクは、グローバルであるということです(でローカライズしない限りlocal $_)。したがって、ループで呼び出す関数が$ _も使用する場合、2つの使用が干渉する可能性があります。

理由がはっきりしないので、これはたまにしか噛みませんが、パッケージ内で使用する場合は通常$_をローカライズします。

于 2011-03-23T12:51:12.877 に答える
1

$_多くの関数のデフォルトパラメータであることを除けば、特別なことは何もありません。明示的にで字句スコープを設定する場合$_myperlは$_グローバルバージョンではなくローカルバージョンを使用します。これには何も奇妙なことはありません。他の名前付き変数と同じです。

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

perlがループ終了時にループ変数の元の値を保持することがわかるまで、出力に少し不思議に思うはずです(perlsynを参照)。

上記のex2に注意してください。$_ここで、2番目のループは、最初のループで宣言された字句スコープを使用しています。微妙ですが、期待されています。この場合も、この値は終了時に保持されるため、2つのループが干渉することはありません。

于 2011-03-23T13:21:15.937 に答える