web-dev-qa-db-ja.com

Perlでの自分とローカルの違いは何ですか?

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

60
Brian G

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

基本的に、myは、変数を作成して、{}、A.K.Aの1つのブロックに固定するものと考えてください。範囲。

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
36
J.J.

簡単な答えは、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が実行されると、スタック上のグローバル$xが再定義されます。 fooからbarが呼び出されると、$xの新しい値2が表示されます。 localを呼び出さなくても同じことが起こるため、これまでのところ特別なことではありません。魔法は、barが返されると、local $xによって作成された動的スコープを終了し、以前のグローバル$xがスコープに戻るということです。したがって、fooの最後の呼び出しでは、$xは1です。

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

54
Jeremy Bourque

Perlの学習 からの引用:

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

したがって、localはグローバル変数の現在の値を保存し、それを何らかの形の空の値に設定します。多くの場合、1行だけではなく、ファイル全体を丸lurみするために使用されます。

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

local $/を呼び出すと、入力レコードセパレーター(Perlが "行"の読み取りを停止する値)を空の値に設定し、宇宙船オペレーターがファイル全体を読み取るため、入力レコードセパレーターにヒットしません。

19
Drew Stephens

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

16

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

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

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

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

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

9
Steve Jessop

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

リンクから:

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

つまり、 'local'は変数の値を一時的に変更しますが、スコープ内ではのみ存在します。

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

7
dlamblin

man perlsubから:

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

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

6
catfood

あなたの混乱は理解できる。語彙のスコープは非常に理解しやすいですが、動的なスコープは珍しい概念です。 mylocalという名前が歴史的な理由で多少不正確(または少なくとも直感的ではない)であるため、状況はさらに悪化しています。

myは、レキシカル変数を宣言します。これは、宣言のポイントから囲んでいるブロック(またはファイル)の終わりまで見える変数です。プログラムの残りの部分で同じ名前を持つ他の変数から完全に独立しています。それはそのブロック専用です。

一方、localは、グローバル変数の値の一時的な変更を宣言します。変更は囲みスコープの終わりで終了しますが、変数は(グローバルであるため)プログラムのどこからでも見ることができます。

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

より詳細な説明については、Mark Jason Dominusの記事 Copingでのスコープ設定 を参照してください。

4
Michael Carman

localは、Perlが動的スコープだけを持っていた時代からのローカライズの古い方法です。字句スコープはプログラマーにとってはるかに自然であり、多くの状況でより安全です。私の変数は、それらが宣言されているスコープ(ブロック、パッケージ、またはファイル)に属します。

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

3
skiphoppy

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

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
2

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

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

2
andy
&s;

sub s()
{
    local $s="5";
    &b;
    print $s;
}

sub b()
{
    $s++;
}

上記のスクリプトは6を出力します。

しかし、ローカルをmyに変更すると、5が出力されます。

これが違いです。シンプル。

0
Saravanarajan

それを覚える最も簡単な方法はこの方法だと思います。 MYは新しい変数を作成します。 LOCALは、既存の変数の値を一時的に変更します。

0
Hawk

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

0
phreakre