my と local どう違う?

ここでは、変数の局所化に使う my と local について解説します。どちらも変数を局所化することには違いないのですが、細かな点で違いがあり、これを理解していないと、想定しない結果となってしまいます。しっかりと押さえておきたいポイントです。

local について

ここでは、local  について解説します。まず、言葉を覚えましょう。local を使って定義された変数は、ダイナミックスコープ変数 と呼びます。そして、local を使って変数を宣言することをダイナミックスコープ宣言と呼びます。

宣言の仕方は

local $var; #宣言のみ
local $var = 'hello'; #宣言と同時に値も同時に格納
local($foo, $var); #複数の変数名を同時に宣言

などです。では、次の例を見てください。

例1
1
2
3
4
5
6
7
8
$var = 'サブルーチンの外';
print $var; #「サブルーチンの外」が出力される
&example;
sub example {
    local $var = 'サブルーチンの中';
    print $var; #「サブルーチンの中」が出力される
}
print $var; #「サブルーチンの外」が出力される
例2
1
2
3
4
5
6
7
8
$var = 'サブルーチンの外';
print $var; #「サブルーチンの外」が出力される
&example;
sub example {
    $var = 'サブルーチンの中';
    print $var; #「サブルーチンの中」が出力される
}
print $var; #「サブルーチンの中」が出力される

お気づきでしょうが、ここまでは、使い方、結果ともに、my とまったく違いはありません。しかし、Perl内部での扱い方は、まったく違うものになっています。local では、変数名は別々に保持されません。言い換えると、local は、グローバル変数に一時的な値を付けるといえます。Perl内部では、それぞれの $var は、同じ変数として認識しており、コードの場所によって、値を付け替えるという作業をしています。そしてどこからその変数が呼び出されたかによって、適用する値が異なってくるのです。それがダイナミックスコープと呼ばれるゆえんです。

上記の通り、local は、グローバル変数に一時的な値を付けるということから、正確に言うとローカル変数を作成するものではないことに注意してください。本当のローカル変数を定義したい場合には、my を使うべきなのです。

最後に、サブルーチンのネストについてご紹介します。my の場合の例とコードの内容は同じなのですが、挙動が異なります。

例3
1
2
3
4
5
6
7
8
9
10
11
$var = 'サブルーチンの外';
&example;
sub example {
    local $var = 'サブルーチンの中';
    print $var; #「サブルーチンの中」が出力される
    &example2;
}
sub example2 {
    print $var; #「サブルーチンの中」が出力される
}
print $var; #「サブルーチンの外」が出力される

注意してみていただきたいのが、9行目です。my の場合には、$var は1行目で宣言された値「サブルーチンの外」が出力されます。ところがこの例の場合では、4行目で宣言された $var の値が引き継がれて表示されます。4行目で宣言されたダイナミックスコープ変数 $var は、サブルーチンが終了するまでの7行目まで有効になります。local で宣言された場合、7行目より前で呼び出されたサブルーチンにも値が引き継がれていくのです。