4

以前、「Effective Perl Programming」の本の関連コンテンツを読んでいましたが、よくわかりませんでした。今日、私は以下のコードのように、これに関する問題に遭遇しました。

my $vname = "a";
my @a = qw(1 2 3);
local @array = @$vname; 
foreach(@array) { print "$_\n"; };

何も出力しません。次に、この行を変更しました。

local @a = qw(1 2 3);  

「my」を「local」に置き換えただけで、機能するようになりました。それで、私はそれらの違いが何であるかを理解したいと思います。

4

5 に答える 5

14

perldocこの質問に答えるエントリが にありますperlfaq7:

動的スコープとレキシカル (静的) スコープの違いは何ですか? local()my()の間

local($x)グローバル変数の古い値を保存し、$xそのサブルーチンから呼び出される他の関数で表示されるサブルーチンの期間に新しい値を割り当てます。これは実行時に行われるため、動的スコープと呼ばれます。local()パッケージ変数または動的変数とも呼ばれるグローバル変数に常に影響します。 my($x)現在のサブルーチンでのみ表示される新しい変数を作成します。これはコンパイル時に行われるため、字句スコープまたは静的スコープと呼ばれます。my()レキシカル変数または(不適切に)静的な(スコープが設定された)変数とも呼ばれるプライベート変数に常に影響します。

例えば:

sub visible {
    print "var has value $var\n";
}

sub dynamic {
    local $var = 'local';   # new temporary value for the still-global
    visible();              #   variable called $var
}

sub lexical {
    my $var = 'private';    # new private variable, $var
    visible();              # (invisible outside of sub scope)
}

$var = 'global';
visible();              # prints global
dynamic();              # prints local
lexical();              # prints global

値「private」がどの時点でも出力されないことに注意してください。これ$varは、関数のブロック内にその値しかなくlexical() 、呼び出されたサブルーチンから隠されているためです。

要約local()すると、プライベートなローカル変数と思われるものは作成されません。グローバル変数に一時的な値を与えます。my() は、プライベート変数が必要な場合に探しているものです。

耐え難いほどの詳細についてはPrivate Variables via my()、in perlsub およびTemporary Values via local()in perlsubを参照してください。

于 2012-08-30T06:00:32.463 に答える
9

my新しい変数を作成します。それが宣言されているレキシカルスコープでのみ見ることができます。

localスコープの終了時に復元されるグローバル変数の一時的なバックアップを作成しますが、そのスコープは縮小しません (引き続きグローバルに表示できます)。新しい変数は作成されません。

my可能な場合は常に使用したいと考えてlocalいますが、グローバル変数を処理する必要がある場合は適切な近似値です (例: $_)。

于 2012-08-30T04:49:48.353 に答える
8

Perl には 2 種類の変数スコープがあります。

  • グローバル変数: それらは現在のパッケージに存在し、外部からアクセスでき、「ローカル」値を持つことができます。この名前は、パッケージ変数のハッシュ/シンボル テーブルである「stash」のキーとして使用できます。
  • レキシカル変数: それらは現在のスコープに存在します (大まかに中括弧で区切られています)。検査できるシンボルテーブルがありません。

レキシカル変数とグローバル変数は干渉しません。同じ名前の 2 つの異なる変数が存在する可能性があります。

ほとんどの Perl 変数マジックは、グローバル変数で発生します。次の構文は、グローバル変数で機能します。

our $var;
$::var;
$main::var;
${'var'};
local $var;

しかしそうではありませんmy $var

したがって、次のように記述できます。

@::array = qw(a b c);
my @secondArray = @{array};

配列をコピーします。変数に格納されている名前で配列を検索することもできます。

@::array = qw(a b c);
my $name = "array";
my @secondArray = @{$name};

最後の行は に省略され… = @$nameます。

レキシカル変数はスタッシュに存在しないため、これは不可能です。

このlocal関数は、現在のスコープ内およびこのスコープ内から呼び出されるすべてのサブルーチンのスコープ (「動的スコープ」) 内のグローバル変数 (およびグローバルのみ) に「ローカル」値を割り当てます。

もともと (Perl 4 では) 参照をシミュレートする唯一の方法は、変数名と stash をいじることでした。これらの使用法は、参考文献が利用可能であるため、現在ではほとんどが 20 年ほど時代遅れになっています (はるかに安全です)。

于 2012-08-30T04:35:05.023 に答える
2

それらを使用する主なケースに焦点を当てたいと思います:

  • myは、特定のブロックに制限したい変数の「デフォルト」にする必要があります。これはほとんどの場合
  • localは、グローバル変数、特定の特殊変数の 1 つを使用する場合に便利です。例えば

    local $/;                          # enable "slurp" mode
    local $_ = <$some_file_handle>;    # whole file now here
    

    local を使用すると、変更が他のコードに影響を与えるのを防ぎます (作成していないモジュールを含む)

于 2012-08-30T06:51:40.093 に答える
0

あなたの場合、違いはlocal、シンボルテーブル内の変数をアドレス指定し、アドレス指定myしないことです。これは、その使用方法のために重要です。

local @array = @$vname;

つまり、あなたは象徴的な参照$vnameとして使用しています (あなたが何をしているのかを知っていることを伝えるには、疑わしい慣行はありません)。クォータ:no strict 'refs'

シンボリック参照から見えるのは、パッケージ変数 (ローカライズされている場合でもグローバル) だけです。(my() で宣言された) レキシカル変数はシンボル テーブルにないため、このメカニズムからは見えません。

したがって、シンボリック参照は、シンボル テーブル内の変数のみを参照できます。@aでレキシカルとして宣言するmyか、 でグローバルとして宣言するかに関係なくlocal、 は@$vnameのみを参照し@main::aます。あなたが言う時

local @a = qw(1 2 3);

、あなたは に新しい価値を与えています@main::a。あなたが言う時

my @a = qw(1 2 3);

、新しいレキシカル変数を作成し@aて値を与えていますが、@main::a未定義のままです。いつ

local @array = @$vname;

次に の値にアクセスし、@main::a未定義であることが判明した場合は の値をそれに設定します@array

すべてが混乱しているように見える場合、それはそれが原因です。strictこれが、 andを使用することを強くお勧めする理由ですwarnings(このコードではかなり爆発するでしょう)。また、自分が何をしているのかを本当に理解していない限り、シンボリック参照を使用することはお勧めしません。

于 2012-08-30T18:24:06.240 に答える