hideden.hatenablog.com

はてなぶろぐー。URLなげー。

レキシカルスコープやらシンボルテーブルやら型グロブやら。

メモっとく。

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 で宣言すると同じ名前に見えて中身が違うとかやれるのがちょっと新鮮だった。