はじめに
Perlからだいぶ離れてますが、復習と備忘録として書いてます。
今回は、Perlの変数管理「シンボルテーブル」と「型グロブ」について記載します。
型グロブ(Typeglob)とは
Perlには $scalar, @array, %hash, &sub に加え、ファイルハンドルやフォーマットなど、同じ名前(識別子)でもシジル($, @, %など)が異なれば、それぞれ別の変数として扱われます。
これらを一括で管理しているデータ構造が「型グロブ」であり、*name という記法で表されます。
$foo = "scalar";
@foo = ("array");
%foo = (key => "hash");
# *foo は上記すべて(スカラー、配列、ハッシュ、ファイルハンドル等)を内包しています
print $foo; # scalar
エイリアシング
型グロブへの代入を行うことで、変数への参照(エイリアス)を作成することができます。
*bar = *foo;
print $bar; # "scalar"
print $bar[0]; # "array"
print $bar{key};# "hash"
これはただの値のコピーではなく、実体へのエイリアスです。したがって、$bar を変更すれば、元の $foo も変更されます。
特定の型だけをエイリアスする
型グロブ全体ではなく、特定の型(例えば配列だけ)をエイリアスすることもできます。
*baz = \@foo; # @baz だけが @foo のエイリアスになる
# $baz や %baz は未定義のまま
これは、定数(読み取り専用スカラー)を定義する際などにも利用されています。
*PI = \3.14159;
# これで $PI は 3.14159 になります
# 読み取り専用となるため、値を書き換えようとするとエラーになります
シンボルテーブルの操作
Perlの変数は、パッケージごとの「シンボルテーブル」というハッシュに格納されています。
main パッケージのシンボルテーブルは %main:: という名前でアクセスできます。
foreach my $sym (keys %main::) {
print "$sym\n";
}
動的なメソッド定義
シンボルテーブルと型グロブを利用すると、プログラム実行中にメソッドを動的に定義することができます。
my %methods = (
get_name => sub { shift->{name} },
set_name => sub { shift->{name} = shift },
get_age => sub { shift->{age} },
);
while (my ($name, $code) = each %methods) {
no strict 'refs';
*$name = $code;
}
no strict 'refs' は、シンボリックリファレンス(文字列を変数名として扱う機能)を許可するために必要です。これにより、大量のアクセサメソッドなどを効率的に生成することができます。
匿名型グロブとファイルハンドル
型グロブはシンボルテーブル(パッケージ変数)に属するため、myで宣言することはできません。そのため、スコープを限定したい場合は local(ダイナミックスコープ)を使用します。
local *foo; # このブロック内でのみ有効な型グロブ
また、Symbol パッケージの gensym を使うと、名前のない型グロブ(匿名型グロブ)を生成できます。これはかつて、ファイルハンドルを動的に生成する際によく使われました。
use Symbol;
my $sym = gensym;
open $sym, "<", "file.txt";
まとめ
- 型グロブは、同じ名前を持つ異なる型(スカラー、配列、ハッシュ、ファイルハンドルなど)をまとめて管理する仕組み
- エイリアスを利用することで、変数の実体を共有したり、動的に関数を定義したりできる
- 型グロブは
myできないため、局所化にはlocalを用いる - シンボルテーブルを操作することで、メタプログラミング的な処理が可能
次回は、変数の値を監視し、特殊な挙動を持たせる「Tied Variables」について解説します。