続・myとourがよくわからん

myとourというか、どうやらPerlのスコープまだよくわかってなかったみたい。

myで宣言した変数はパッケージじゃなくてスコープに対して所属しているから、シンボルテーブルを覗いて見つかったら逆に問題なんじゃないだろうか。で、一番外側にあるスコープはファイルそのものだから、宣言した行からあと、スコープを抜けるまで、つまりファイルの最後まで存在してる。

myがスコープに属しているというはわかってたのだけど、てっきりpackageにもスコープがあるものとばかり。id:seamlessbiasさんthxです。

えと、つまり、

use warnings;
use strict;

package main;
my $var_main;

package foo;
my $var_foo;

というコードがあったら、$var_mainも$var_fooのどちらもこのファイルのスコープに属することになるわけか。

たしかに、

use warnings;
use strict;

package main;
my $name;

package foo;
my $name;

とすると、'"my" variable $name masks earlier declaration in same scope at pkg_test_for_blog.pl line 8.'とおこられた。

package宣言でパッケージのスコープが出来ないということは、同じファイルの中に普通にパッケージを定義しても、レキシカル変数を隠蔽できるというメリットはないわけか。だから、普通はファイルごとにpackageを定義して、それでスコープを制限しているのだな。

一つのファイルで同じことをするとなると、

use warnings;
use strict;

package main;
my $name;

{
    package foo;
    my $name;
}

ってことね。ていうか、この書き方は、かなりリャマ本あたりで見た気がしてきた。

で、一番はじめの疑問にもどろう。ここまでの考察を参考に、fooパッケージのためだけのスコープの中に$nameというレキシカル変数を定義する。さらにそれを、サブルーチンを経由して取り出してみた。

use warnings;
use strict;

{
    package foo;
    my $name = 'foo';
    sub get_name {return $name;}
}

my $name = 'main';

print "$name\n";
print foo::get_name(), "\n";

実行結果は、

main
foo

となるので、正しくとりだせている。一番の問題はこのfoo:get_name()がとりだした$nameがどこにあるかだ。普通は、スコープを抜けてからはそのスコープ内のレキシカル変数にアクセスできないはず。でも、foo:get_name()はアクセスできてるわけだ。うーん、なんでだ。明日学校でラクダ本あたりとにらめっこして見るかなぁ。