シンボルテーブルとmy
my,our,localについて勉強しなおしていて下記サイトのコードサンプルを実行中に疑問がわいたので記す。
- Perl/codepiece/my_and_locals1 - Glamenv-Septzen.net
こちらmyの挙動を試しているのが下記。(以下:コードmy1)
- 「myによる字句解析的(lexical)なスコープ決定」コードピース(1)
#!/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)
- 「大量のtry&errorの果てに。」コードピース (5) : 同じファイル中で、パッケージを切り替えてmyをするとどうなるか。
#!/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の勉強はまだ完了してないので、理解し終えてから別エントリとしたい。