69

デバッグしようとしているこのスクリプトで両方が使用されているのを見ていますが、文献は明確ではありません。誰かが私のためにこれをわかりやすく説明できますか?

4

15 に答える 15

61

簡単な答えはmy、レキシカルスコープでlocal変数をプライベートとしてマークし、動的スコープで変数をプライベートとしてマークすることです。

my通常の意味でローカル変数を作成するため、理解しやすいです。作成された新しい変数があり、通常は中括弧でマークされている囲み字句ブロック内でのみアクセスできます。中括弧の規則には、次のようないくつかの例外があります。

foreach my $x (@foo) { print "$x\n"; }

しかし、それはPerlがあなたの言いたいことをしているだけです。通常、次のようなものがあります。

sub Foo {
   my $x = shift;

   print "$x\n";
}

その場合、$xサブルーチンに対してプライベートであり、そのスコープは中括弧で囲まれています。これは とは対照的であることに注意してください。変数localのスコープはmy、ファイルに記述されているコードに対して定義されるということです。これはコンパイル時の現象です。

を理解するlocalには、実行中のプログラムの呼び出しスタックの観点から考える必要があります。変数が の場合、スタック上のそれより下のすべてに対してステートメントが実行localされた時点から、.localを含むブロックの呼び出し元にスタックを戻すまで再定義されますlocal

これは最初は混乱する可能性があるため、次の例を検討してください。

sub foo { print "$x\n"; }
sub bar { local $x; $x = 2; foo(); }

$x = 1;
foo(); # prints '1'
bar(); # prints '2' because $x was localed in bar
foo(); # prints '1' again because local from foo is no longer in effect

foo初めて呼び出されると、グローバル値$xが 1であることがわかります。barが呼び出されて実行されると、スタック上local $xのグローバルが再定義されます。が から呼び出されると、 の新しい値 2 が表示され$xます。への呼び出しがなくても同じことが起こっていたので、これはそれほど特別なことではありません。マジックは、返されるときに、によって作成された動的スコープを終了し、以前のグローバルがスコープに戻ることです。したがって、 の最終呼び出しの場合、は 1 です。foobar$xlocalbarlocal $x$xfoo$x

my探しているローカル変数が得られるため、ほとんどの場合、 を使用したいと思うでしょう。ブルームーンに一度、localクールなことをするのに本当に便利です。

于 2008-09-24T20:26:41.323 に答える
43

動的スコーピング。きちんとしたコンセプトです。多くの人はそれを使用していないか、理解していません。

基本的にmy、変数を作成して、{} の 1 つのブロック、AKA スコープに固定すると考えてください。

my $foo if (true); # $foo lives and dies within the if statement.

したがって、my変数はあなたが慣れているものです。一方、動的スコープでは $var はどこでも宣言でき、どこでも使用できます。したがって、local基本的にそのグローバル変数の使用を一時停止し、「ローカル値」を使用してそれを操作します。したがってlocal、一時変数の一時スコープを作成します。

$var = 4;
print $var, "\n";
&hello;
print $var, "\n";

# subroutines
sub hello {
     local $var = 10;
     print $var, "\n";
     &gogo; # calling subroutine gogo
     print $var, "\n";
}
sub gogo {
     $var ++;
}

これは次のように表示されます。

4
10
11
4
于 2008-09-24T20:24:08.863 に答える
26

Learning Perlからの引用:

しかし、ローカルの名前は間違っているか、少なくとも誤解を招くような名前になっています。私たちの友人であるチップ・サルゼンバーグは、タイムマシンで1986年に戻ってラリーにアドバイスをする機会があれば、代わりに「セーブ」という名前でローカルに電話するようにラリーに言うだろう. これは、 local が実際に指定されたグローバル変数の値を保存するため、後で自動的にグローバル変数に復元されるためです。(そうです: これらのいわゆる「ローカル」変数は実際にはグローバルです!) この保存と復元のメカニズムは、foreach ループの制御変数と @_ で既に 2 回見たものと同じです。サブルーチン パラメータの配列。

したがって、localグローバル変数の現在の値を保存してから、何らかの形式の空の値に設定します。行頭だけでなく、ファイル全体を丸呑みするために使用されることがよくあります。

my $file_content;
{
    local $/;
    open IN, "foo.txt";
    $file_content = <IN>;
} 

を呼び出すlocal $/と、入力レコード区切り文字 (Perl が「行」の読み取りを停止する値) が空の値に設定され、spaceship オペレーターがファイル全体を読み取るようになるため、入力レコード区切り文字にヒットすることはありません。

于 2008-09-24T22:58:10.507 に答える
18

この問題に関するマーク・ジェイソン・ドミナスの徹底的な論文に誰もリンクしていないとは信じられません。

于 2008-09-25T23:25:27.733 に答える
9

http://perldoc.perl.org/perlsub.html#Private-Variables-via-my()

local 演算子によって作成された動的変数とは異なり、 my で宣言されたレキシカル変数は、呼び出されたサブルーチンを含め、外部の世界から完全に隠されています。これは、それ自体または他の場所から呼び出された同じサブルーチンである場合に当てはまります。すべての呼び出しは独自のコピーを取得します。

http://perldoc.perl.org/perlsub.html#Temporary-Values-via-local()

ローカルは、そのリストされた変数を、囲んでいるブロック、eval、または do FILE に対して「ローカル」になるように変更します。また、そのブロック内から呼び出されるサブルーチンに対しても変更します。ローカル変数は、一時的な値をグローバル (つまりパッケージ) 変数に与えるだけです。ローカル変数は作成しません。これは、動的スコープとして知られています。レキシカル スコープは、C の auto 宣言のように機能する my で行われます。

「囲んでいるブロックにローカル」ということは、ブロックが終了すると元の値が復元されることを意味するということを除けば、これはまったく不明確ではないと思います。

于 2008-09-24T20:21:35.623 に答える
7

さて、Googleはこれで本当にあなたのために働いています: http://www.perlmonks.org/?node_id=94007

リンクから:

簡単な要約: 「my」は新しい変数を作成し、「local」は変数の値を一時的に修正します。

つまり、「local」は variable の値を一時的に変更しますが、それが存在するスコープ内でのみ 変更します。

通常は my を使用します。より高速で、奇妙なことは何もしません。

于 2008-09-24T20:14:02.117 に答える
6

からman perlsub:

local 演算子によって作成された動的変数とは異なり、 my で宣言されたレキシカル変数は、呼び出されたサブルーチンを含め、外部の世界から完全に隠されています。

したがって、単純化しすぎるとmy、変数は宣言されている場所でのみ表示されます。localコールスタックの下にも表示されます。通常はmyの代わりに使用しますlocal

于 2008-09-24T20:18:10.017 に答える
4

あなたの混乱は理解できます。字句スコープはかなり理解しやすいですが、動的スコープは珍しい概念です。状況は名前によって悪化し、my歴史local的な理由からやや不正確(または少なくとも直感的ではない)になっています。

my字句変数を宣言します。これは、宣言の時点からそれを囲むブロック(またはファイル)の終わりまで表示されます。これは、プログラムの他の部分で同じ名前を持つ他の変数から完全に独立しています。そのブロックにプライベートです。

local一方、は、グローバル変数の値への一時的な変更を宣言します。変更は囲んでいるスコープの最後で終了しますが、変数(グローバル)はプログラムのどこにでも表示されます。

経験則として、を使用myして独自の変数を宣言し、localPerlの組み込み変数への変更の影響を制御します。

より詳細な説明については、MarkJasonDominusの記事「Scopingへの対処」を参照してください。

于 2008-09-25T02:00:13.330 に答える
3

local は、Perl が動的スコープのみを持っていた時代からの古いローカリゼーション方法です。レキシカルスコープは、プログラマーにとってより自然で、多くの状況でより安全です。my 変数は、宣言されているスコープ (ブロック、パッケージ、またはファイル) に属しています。

代わりに、ローカル変数は実際にはグローバル名前空間に属します。local で変数 $x を参照する場合、実際にはグローバル変数である $main::x を参照しています。その名前が示すものとは反対に、すべての local が行うことは、このブロックの最後まで新しい値を $main::x の値のスタックにプッシュすることであり、その時点で古い値が復元されます。それ自体は便利な機能ですが、多くの理由でローカル変数を持つのは良い方法ではありません (スレッドがある場合に何が起こるかを考えてみてください。あなたはローカライズしました!)。しかし、Perl 5 より前の悪しき時代には、ローカル変数のように見える変数を持つ唯一の方法でした。

于 2008-09-25T18:52:22.490 に答える
2

次のコードとその出力を見て、違いを理解してください。

our $name = "Abhishek";

sub sub1
{
    print "\nName = $name\n";
    local $name = "Abhijeet";

    &sub2;
    &sub3;
}

sub sub2
{
    print "\nName = $name\n";
}

sub sub3
{
    my $name = "Abhinav";
    print "\nName = $name\n";
}


&sub1;

出力は次のとおりです。

Name = Abhishek

Name = Abhijeet

Name = Abhinav
于 2013-04-10T05:44:22.113 に答える
2

「my」変数は、現在のコード ブロックでのみ表示されます。「ローカル」変数も、以前に表示されていた場所に表示されます。たとえば、「my $x;」と言うと、サブ関数を呼び出すと、その変数 $x を認識できません。しかし、「local $/;」と言うと (レコード区切りの値を無効にするため)次に、呼び出す関数でファイルからの読み取りが機能する方法を変更します。

実際には、ほとんどの場合、「ローカル」ではなく「自分」が必要です。

于 2008-09-24T20:18:36.240 に答える
0

サブルーチン内で呼び出されるサブルーチンがある場合にのみ異なります。たとえば、次のようになります。

sub foo { 
    print "$x\n"; 
}
sub bar { my $x; $x = 2; foo(); }
    
bar(); 

バー$xによって制限され、呼び出されたサブルーチンからは見えないため、何も出力しません。次に例を示します。{}

sub foo { print "$x\n"; }

sub bar { local $x; $x = 2; foo(); }
   
bar(); 

ローカル変数は呼び出されたサブルーチンに表示されるため、2 が出力されます。

于 2021-08-14T11:50:39.917 に答える
0

local を使用してレコード区切り文字を再定義するディノマイトの例は、多くの perl プログラミングで遭遇した唯一の例です。私はニッチな perl 環境 [セキュリティ プログラミング] に住んでいますが、私の経験ではめったに使用されないスコープです。

于 2008-10-01T16:01:16.710 に答える