ここでは、my について解説します。my は、Per5 から実装された関数で、Perl4 では使えません。Perl4 では local のみが使えましたが、Perl5 では、my を使うのが一般的ですので、しっかりと理解してください。

まず、言葉を覚えましょう。my を使って定義された変数は、レキシカルスコープ変数 と呼びます。そして、my を使って変数を宣言することをレキシカルスコープ宣言と呼びます。

宣言の仕方は

my $var;           #宣言のみ
my $var = 'hello'; #宣言と同時に値も同時に格納
my($foo, $var);    #複数の変数名を同時に宣言
などです。では、レキシカルスコープ変数の有効範囲は、どこまでかと言うと、次の例を見てください。
 1| $var = 'サブルーチンの外';
 2| print $var;                       #「サブルーチンの外」が出力される
 3| &example;
 4| sub example {
 5|     my $var = 'サブルーチンの中';
 6|     print $var;                   #「サブルーチンの中」が出力される
 7| }
 8| print $var;                       #「サブルーチンの外」が出力される

この場合、 2 行目で出力される値は、「サブルーチンの外」ですね。そして 6 行目で出力される値は「サブルーチンの中」となります。サブルーチンの中で、$var のレキシカルスコープ宣言をしているため、新たにメモリー上に値が保持されることになります。もちろん、2 行目で定義した $var の値も保持されたままです。それぞれの  $var は、同じ名前にもかかわらず、変数名も値も、別々に保持されます。つまり、それぞれの $var は、名前は同じですが、まったく別の変数として処理されます。ただし、5 行目のサブルーチン内で定義された $var の変数名と値は、サブルーチンを抜けた時点で、破棄されてしまいます。

では、8 行目では、何か出力されるのでしょうか。上の説明でお分かりかと思いますが、「サブルーチンの外」が出力されるわけです。サブルーチンの外からは、5 行目で定義した値は参照できないことに注意してください。

次に、5 行目で my を使って宣言しなかった場合には、どうなるでしょうか。

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

上記の通り、8 行目の値が変わってしまいましたね。5 行目で my を使って局所化していなかったため、1 行目で代入した値が、5 行目で書き換わってしまったのです。そのため、8 行目の出力結果も変わってしまったというわけです。意図的にそうしたいのであれば問題ないのですが、そうでなかったら、バグになってしまいますね。

次に、サブルーチンがネスト(入れ子)になったパターンを紹介します。ここで言っているネストとは、サブルーチンの中でサブルーチンを呼び出した場合のことを指しています。

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

この例では、4 行目でレキシカルスコープ変数として $var を宣言していますので、この $var の有効範囲は、7 行目までとなります。しかし、その手前の 6 行目でサブルーチン example2 を呼び出していますね。その場合、4 行目で宣言された $var は example2 の中でも有効になるのでしょうか。答えは、No です。9 行目で呼び出している $var は、グローバル変数の $var で、1 行目で宣言されたものなんです。

話が若干それますが、もし、変数をサブルーチンに引き継ぎたい場合には、以下の例のように、引数をを正しく与えてるべきです。

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

<< 戻る

次へ >>

戻る

会社案内 | 特定商取引法に基づく表示 | プライバシーポリシー | 当サイトへのリンクについて | お問い合わせ