ローカル変数と範囲
localとmy
サブルーチンを使うようになると、サブルーチンの領域はメインルーチンとは別物になります
しかし、その別物の領域の中の変数に他のルーチンからアクセスできた場合、困ったことがおこります
サブルーチンの目的はプログラムの再利用です。しかしその中で変数名まで定義されると困りますね
サブルーチンの中で$aryという変数があった場合、他のルーチンで$aryは使えなくなります(使うと値が変更されるのでおかしくなる)
結果として変数名に制限がでるし、いらない気苦労が多発しそうです
これではせっかくのプログラムの再利用も、逆にプログラマの首をしめることになりかねません
そこで、サブルーチンの中の変数はサブルーチンの中だけで使えるようにします
この変数のことをローカル変数と呼びます
逆に、どのルーチンからでも参照できる変数をグローバル変数と呼びます
以下のプログラムを見てください
$var = "メインルーチン";
print "$var\n";
&test;
print "$var\n";
sub test {
$var = "サブルーチンで書きかえ";
}
サブルーチン&testを実行すると、サブルーチン内で$varへアクセスして内容を書き換えます
つまり、私たちが使ってきたこれまでの変数は全てグローバル変数だったのです
Perl言語の場合、ローカル変数を作成するにはローカル変数の宣言をする必要があります
しかもPerl言語にはローカル変数が二種類存在します
ひとつは local で宣言されたローカル変数です。もうひとつは my で宣言されたローカル変数です
local($var1 , $varn...)
my($var1 , $varn...)
ローカル変数はこのようにして、localかmy宣言子で宣言して()の中にカンマで区切って複数同時に宣言できます
localで宣言した変数は、宣言したルーチンで呼び出したルーチンからのアクセスを許します
myで宣言した変数は、宣言したルーチンでのみ参照できます
ただしmyでは特殊変数を扱えません、そのような場合にlocalを使います
ローカル変数の仕様を考えれば、基本的にはmyを使うことを推奨されます
localは、他言語で言う「フレンド」的な変数です
そのルーチンで呼び出したルーチンからのアクセスを許すため、上手に使う必要があります
&sub1;
sub sub1 {
local($local_var) = "目からビーム!";
my($my_var) = "口からバズーカ";
print "【宣言ルーチン】\n";
print "local \t= $local_var\nmy \t= $my_var\n\n";
&sub2;
}
sub sub2 {
print "【呼び出しルーチン】\n";
print "local \t= $local_var\nmy \t= $my_var";
}
結果は次のようになります
【宣言ルーチン】
local = 目からビーム!
my = 口からバズーカ
【呼び出しルーチン】
local = 目からビーム!
my =
ご覧のとうり、localで宣言した変数は呼び出したルーチンからも参照することができます
それに対し、myは宣言したルーチンでのみ参照できるため、データーの隠蔽度が高いです
このプログラムでは、sub2での変数$my_varはこのルーチンではじめて宣言されています(だから呼び出しても空文字(0)です)
他のルーチンから参照するような特別な理由があるか、特殊変数を使わないかぎりmyで宣言するのが基本です
また、ローカル変数の指定範囲はルーチン単位だけではなく、ブロック単位 { } でも可能です
&my_sub;
sub my_sub {
my($var) = "THE YELLOW MONKEY";
print "ルーチン内(最初)\t= $var\n";
{
print "ブロック内(宣言前)\t= $var\n";
my($var) = "吉井さんラヴ☆";
print "ブロック内(宣言後)\t= $var\n";
}
print "ルーチン内(最後)\t= $var\n";
}
{
print "ブロック内(宣言前)\t= $var\n";
my($var) = "吉井さんラヴ☆";
print "ブロック内(宣言後)\t = $var\n";
}
この部分がサブルーチン内のブロックです
myで宣言された変数は、同じルーチン内では参照可能なので
ブロック内(宣言前)はルーチン内(最初)と同じ値を返します
しかし、ブロック内で宣言されたmyはブロック内でしか参照できません
ブロックからでれば、ブロック内で宣言された$varは破棄され、サブルーチンの最初で宣言された$varが最優先で参照されるようになります
ルーチン内(最初) = THE YELLOW MONKEY
ブロック内(宣言前) = THE YELLOW MONKEY
ブロック内(宣言後) = 吉井さんラヴ☆
ルーチン内(最後) = THE YELLOW MONKEY
同名のグローバル変数とローカル変数のアクセス優先順位もこれと同様です
そのルーチンやブロックのローカル変数をプログラムは最優先にアクセスします
また、そのルーチンやブロックを抜けてローカル変数が破棄されれば、最も近いローカル変数を参照します
$var = "花子の奥まで太郎を入れたい";
print "グローバル(最初)\t= $var\n\n";
&my_sub;
print "グローバル(最後)\t= $var\n";
sub my_sub {
my($var) = "\tTHE YELLOW MONKEY";
print "ルーチン内(最初)\t= $var\n\n";
{
my($var) = "\t\t吉井さんラヴ☆";
print "ルーチンブロック内\t= $var\n\n";
}
print "ルーチン内(最後)\t= $var\n\n";
}
結果はもう予想できると思います
グローバル変数とローカル変数は、実用的なプログラム作成には欠かせなくなります
実用的プログラムの作成は、これまでのサンプルとはけた違いの長いプログラムになるでしょう
そんなとき、変数名がゴチャゴチャにならないよう気をつけてください