シンボルテーブルとmy

my,our,localについて勉強しなおしていて下記サイトのコードサンプルを実行中に疑問がわいたので記す。

こちらmyの挙動を試しているのが下記。(以下:コードmy1)

#!/usr/bin/perl

my $compile_time = 123;
$compile_time = 456;

print join " ", keys(%::);
print "\n----------\n";
print "main::compile_time = [", $main::compile_time, "]\n";
print "::compile_time = [", $::compile_time, "]\n";
print "compile_time = [", $compile_time, "]\n";

これを実行しシンボルテーブルには存在するのにアクセスできないとしている。


その後でてくるパッケージ切り替えとmyの挙動の試行。(以下:コードtry5)

#!/usr/bin/perl

print "package=[", __PACKAGE__, "]\n";
print '%:: = ', join(" ", keys(%::)), "\n";
print '%hoge:: = ', join(" ", keys(%hoge::)), "\n";

my $var1;
$var1 = "abc";

この実行結果として%:: = にvar1が出てこず当然、とされているのだがこれが気になった。


コードmy1とコードtry5との差を考え、下記コードを実行。

#!/usr/bin/perl

my $compile_time = 123;
$compile_time = 456;

print join " ", keys(%::);

これがコードmy1におけるコードtry5とほぼ同等のコードでる。
実行してみるとシンボルテーブルにcompile_timeは存在しない。


オリジナルのコードmy1においてシンボルテーブルにcompile_timeが存在した理由は、シンボルテーブルの参照後に

print "main::compile_time = [", $main::compile_time, "]\n";

または

print "::compile_time = [", $::compile_time, "]\n";

として、表示のためにcompile_timeを参照した際にシンボルテーブルにも書き込まれたというのが結論のようだ。
これは下記でも述べられているようにコンパイル時にシンボルテーブルに書かれるのでコードの後半にパッケージ変数の参照があって冒頭でシンボルテーブル一覧を表示すると載っているのは自然な挙動だ。


他人のサイトの指摘に終始してしまったが、大変勉強になりました。
msakamoto-sfさんありがとうございます。


なんとなく適当に俺々ツール作りに使っている、perl。奥が深い。
my,our,localの勉強はまだ完了してないので、理解し終えてから別エントリとしたい。

参考にしたサイト

上記サイトはコメント、トラックバックができないようなので、同一著者のはてダにTB。

元々はここのトラックバックで見つけた記事。