2

変数を受け取り、データベースからの情報を表示する次のメソッドがあります。

sub showResult {
    if (@_ == 2) {
        my @results = dbGetResults($_[0]);
        if (@results) {
            foreach (@results) {
                print "$count - $_[1] (ID: $_[0])\n";
            }
        } else {
            print "\n\nNo results found";
        }
   }
}

foreachループの印刷行を除いて、すべて正常に機能します。この$_変数には、メソッドに渡された値が引き続き含まれています。

$ _に新しい値のスコープを「強制」する方法はありますか、それとも常に元の値が含まれますか?

$ _のスコープがどのように機能するかを説明する優れたチュートリアルがあれば、それもすばらしいでしょう。

ありがとう

4

3 に答える 3

9

ここでの問題は、@_代わりにreally を使用していることです$_foreachループの変更$_、スカラー変数ではなく@_、 でインデックスを付けた場合にアクセスしているものです$_[X]。また、コードをもう一度チェックして、その内容を確認してください@results。配列または参照の配列である場合は、間接${$_}[0]またはそのようなものを使用する必要がある場合があります。

于 2011-09-20T19:11:08.463 に答える
2

他の人が指摘しているように:

  • あなたは実際に使用していて、印刷ステートメントでは使用@_していません。$_
  • これらの変数は他の場所で使用されるため、これらの変数に何かを保持するのは良くありません。

公式には、$_and@_はグローバル変数であり、どのパッケージのメンバーでもありません。スコープをローカライズできますがmy $_、それはおそらく本当に悪い考えです。問題は、Perl が知らないうちにそれらを使用できることです。数行以上の値に依存するのは悪い習慣です。

可能な限り依存関係を取り除くために、プログラムをわずかに書き直します@_$_

sub showResults {
    my $foo = shift;    #Or some meaningful name
    my $bar = shift;    #Or some meaningful name

    if (not defined $foo) {
       print "didn't pass two parameters\n";
       return;  #No need to hang around
    }
    if (my @results = dbGetResults($foo)) {
        foreach my $item (@results) {
        ...
    }
}

いくつかの変更:

  • 以前shiftは、2 つのパラメーターに実際の名前を付けていました。foobarは良い名前ではありませんが、由来がわからなかったdbGetResultsので、お探しのパラメーターがわかりませんでした。パラメータが渡される@_と はまだ使用されており、 myshiftは の値に依存していますが@_、最初の 2 行の後は自由です。
  • 2 つのパラメーターには実際の名前があるため、 を使用しif (not defined $bar)て、両方のパラメーターが渡されたかどうかを確認できます。これもマイナスに変えました。このようにして、両方のパラメーターが渡されなかった場合は、早期に終了できます。このようにして、コードのインデントが 1 つ減り、サブルーチン全体を占める if 構造がなくなります。コードを理解しやすくなります。
  • foreach my $item (@results)の代わりに使用しforeach (@results)、依存しています$_$_->[0]繰り返しますが、プログラムが何をしているのかがより明確になり、混乱することはありません$_[0](それがあなたがしていたことだと思います)。あなたが望んでいたことは明らかだったでしょう$item->[0]
于 2011-09-20T20:34:47.473 に答える