シンボルテーブルとグロブ

シンボルテーブル、名前空間、グロブ

シンボルテーブル

Perlで宣言される変数にはグローバルなものと、そうでない、レキシカル変数*1とがあります。

このグローバル変数には値が格納されています。この、グローバル変数の値が格納されている場所はシンボルテーブルと呼ばれています。

すでにこの辺りで混乱する人がほとんどなので、実際にそのシンボルテーブルを見てみます。
お時間があればぜひ実際にコーディングして見てください。

1. スクリプト

#!/usr/bin/perl
use strict;
use warnings;

### シンボルテーブル
my $symtab = {%main::};

for my $key( sort keys %{$symtab} ) {
    warn '-' x 50;
    warn "key: " . $key;
    warn "val: " . $symtab->{$key}; # glob
}

2. 実行

:!perl %
-------------------------------------------------- at script/pkg.pl line 9.
key: at script/pkg.pl line 10.
val: *main: at script/pkg.pl line 11.
-------------------------------------------------- at script/pkg.pl line 9.
key:  at script/pkg.pl line 10.
val: *main:: at script/pkg.pl line 11.
-------------------------------------------------- at script/pkg.pl line 9.

...

-------------------------------------------------- at script/pkg.pl line 9.
key: utf8:: at script/pkg.pl line 10.
val: *main::utf8:: at script/pkg.pl line 11.
-------------------------------------------------- at script/pkg.pl line 9.
key: warnings:: at script/pkg.pl line 10.
val: *main::warnings:: at script/pkg.pl line 11.

シンボルテーブルをたどるとグロブがでてくる

たとえば$aという変数は、このシンボルテーブルをたどるとどこに格納されているかがわかります。

もうこの辺りでいっぱい、いっぱいになっている人がほとんどなので、実際にスクリプトを見てみましょう。
お時間があればぜひ実際にコーディングして見てください。

1. スクリプト

#!/usr/bin/perl
use strict;
use warnings;

my $symtab = {%main::};

### グローバル変数
our $hoge=1;
warn $symtab->{hoge};

2. 実行

:!perl %
*main::hoge at script/pkg.pl line 9.

アスタリスクで始まっているものがグロブと呼ばれるものです。

グロブは記憶領域と名前をマッピングする構造体

とりあえずアスタリスクで始まっているものがグロブだと言われても意味不明なので次のスクリプトをご覧ください。

1. スクリプト

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

our $hoge = 1;
our @hoge = (1, 2, 3);
our %hoge = ( x => 1, y => 2 );

warn Dumper *main::hoge{SCALAR};
warn Dumper *main::hoge{ARRAY};
warn Dumper *main::hoge{HASH};

2. 実行

:!perl %
$VAR1 = \1;
$VAR1 = [
          1,
          2,
          3
        ];
$VAR1 = {
          'y' => 2,
          'x' => 1
        };

またmain::を省略することもできます。

warn Dumper *hoge{SCALAR};
warn Dumper *hoge{ARRAY};
warn Dumper *hoge{HASH};

グロブへの割り当て

グローバル変数の宣言をした後、を次のように代入することもできます。

1. スクリプト

#!/usr/bin/perl
use strict;
use warnings;

our $hoge;
our @hoge;

グロブhogeを
*main::hoge = \'hogehoge';
*main::hoge = [ 1, 2, 3];

warn $hoge; # シンボルテーブルが$hogeのリファレンスにマップする
warn @hoge; # シンボルテーブルが@hogeのリファレンスにマップする

2. 実行

:!perl %
hogehoge at script/glob3.pl line 11.
123 at script/glob3.pl line 12.

今日のまとめ

Perlが上記スクリプトを実行した際に、データを変数へ代入しているのですが、その変数の仕組みを少しだけ紹介しました。

  • シンボルテーブルは、記憶領域と名前をマップしています。
  • シンボルテーブルがマップしているのはグロブです。
  • グロブの中には$hoge, @hoge, %hogeといった同一の名前のリファレンスを保持しています。
  • グロブの中にはデータそのものではなく、リファレンスが格納されている。

ところで、次の処理をご覧ください。

warn $hoge;

「この処理は、スカラー変数hogeに格納されている値をstderrで出力します。」と答えていた貴方も今日からは、
「この処理は$hogeをルックアップしています。シンボルテーブル*2からグロブ*3を参照することができます。そのグロブにはスカラー値を格納しているデータ領域のリファレンスが記録されています。結果、その格納された値をstderrで出力しています。」と格好よく*4答えられると思います。

本当に?

*1:myで宣言されている

*2:%main::

*3:*hoge

*4:正直この文章が正確かどうかは自身がない