レキシカルスコープやらシンボルテーブルやら型グロブやら。
メモっとく。
use strict; our $hoge = 'HOGE'; my $hoge = 'hoge'; print $hoge; # hoge print ${hoge}; # hoge print $::hoge; # HOGE print $main::hoge; # HOGE print $::main::hoge; # HOGE print ${*hoge{SCALAR}}; # HOGE 型グロブからスカラー変数のリファレンスもらってデリファレンス no strict 'refs'; my $name = 'hoge'; sub name { 'hoge' }; print ${"hoge"}; # HOGE print $$name; # HOGE print ${$name}; # HOGE print ${name()}; # HOGE シンボリックリファレンスは名称orリファレンスを返す関数呼び出しでも可
になる。
- Perl にはシンボルテーブルとレキシカルスコープの2種類の変数名テーブルがあるらしい
- シンボルテーブルは名前空間(package)に所属。明示しなければmain空間
- my 宣言を何のスコープにもかかってないところで行っても、global変数にはならない (ファイルスコープのレキシカル変数になる)
- $hogeと${hoge}は完全に等価。${"hoge"}はシンボリックリファレンスのデリファレンス
- シンボリックリファレンスのデリファレンスは、シンボルテーブルに登録されたglobal変数のみが対象
- 型グロブで色々やるのはシンボルテーブルの話。レキシカルスコープのはいじれない
最初の宣言を逆にすると
use strict; my $hoge = 'hoge'; our $hoge = 'HOGE'; print $hoge; # HOGE print ${hoge}; # HOGE print $::hoge; # HOGE print $main::hoge; # HOGE print $::main::hoge; # HOGE print ${*hoge{SCALAR}}; # HOGE no strict 'refs'; my $name = 'hoge'; sub name { 'hoge' }; print ${"hoge"}; # HOGE print $$name; # HOGE print ${$name}; # HOGE print ${name()}; # HOGE
全部"HOGE"になる。で、こういうことをしてみる。
use strict; our $hoge = 'HOGE'; print \$::hoge; # SCALAR(0x814eccc) print \$hoge; # SCALAR(0x814eccc) my $hoge = 'hoge'; print \$::hoge; # SCALAR(0x814ecb4) print \$hoge; # SCALAR(0x814eccc)
use strict; my $hoge = 'hoge'; print \$::hoge; # SCALAR(0x814ecd8) print \$hoge; # SCALAR(0x814eca8) our $hoge = 'HOGE'; print \$::hoge; # SCALAR(0x814ecd8) print \$hoge; # SCALAR(0x814ecd8)
use strict; print \$::hoge; # SCALAR(0x814ecb4) my $hoge = 'hoge'; print \$::hoge; # SCALAR(0x814ecb4) print \$hoge; # SCALAR(0x814eca8) { my $hoge = 'hogehoge'; print \$hoge; # SCALAR(0x814eccc) }
use strict; print \$::hoge; # SCALAR(0x814ecb4) our $hoge = 'hoge'; print \$::hoge; # SCALAR(0x814ecb4) print \$hoge; # SCALAR(0x814ecb4)
- 突然Global変数にアクセスしても勝手に作成される
- use strict; でもパッケージ名付けると怒られない
- my はレキシカルスコープのみに変数を登録し、ourはシンボルテーブルとレキシカルスコープの両方に登録する
- our はglobal変数だけじゃなく、レキシカル変数も上書き宣言する
- our は既に存在するglobal変数を宣言しても別に何も怒らない
- 違うレキシカルスコープでmy宣言すると新しく割り当てられる
この調べ方が正しいかどうかは謎。でも個人的には色々納得できた。きっかけはd:id:a666666:20080124:1201177376。
初めてらくだ本読んだ!ありがとう刺身さま。
ってか、eval()の場合とかlocalがどーなんだとか型グロブ云々だとか変数の探索順だとか色々調べたけど面倒だから略。
our → my で宣言すると同じ名前に見えて中身が違うとかやれるのがちょっと新鮮だった。