=head1 名前 perlpragma - ユーザプラグマの書き方 =head1 説明 プラグマとは, C や C といったような, Perl の コンパイル時若しくは実行時のある状況に影響を与えるモジュールのことです. Perl 5.10 ではもう組み込みのプラグマだけに制限されません; レキシカル スコープでユーザ機能の振る舞いを偏光するユーザプラグマを作成することが できます. =head1 基本的な例 例えば, 算術演算のオーバーロードを行うクラスを作る必要があり, それを以下のように C 風に提供したいとします. use MyMaths; my $l = MyMaths->new(1.2); my $r = MyMaths->new(3.4); print "A: ", $l + $r, "\n"; use myint; print "B: ", $l + $r, "\n"; { no myint; print "C: ", $l + $r, "\n"; } print "D: ", $l + $r, "\n"; no myint; print "E: ", $l + $r, "\n"; 対応する出力: A: 4.6 B: 4 C: 4.6 D: 4 E: 4.6 I<つまり>, C の影響下にある場所では加算は整数で行われ, 一方デフォルトではそうではなく(浮動小数点でもおこなわれる), C を使うことでデフォルトの振る舞いに戻すことも出来ます. C パッケージの最小の実装は次のようになるでしょう: package MyMaths; use warnings; use strict; use myint(); use overload '+' => sub { my ($l, $r) = @_; # Pass 1 to check up one call level from here if (myint::in_effect(1)) { int($$l) + int($$r); } else { $$l + $$r; } }; sub new { my ($class, $value) = @_; bless \$value, $class; } 1; ユーザプラグマ C を空のリスト C<()> でロードすることで その C が呼び出されないようにしています. Perl のコンパイル時の動作は C パッケージに対して作用します: package myint; use strict; use warnings; sub import { $^H{myint} = 1; } sub unimport { $^H{myint} = 0; } sub in_effect { my $level = shift // 0; my $hinthash = (caller($level))[10]; return $hinthash->{myint}; } 1; プラグマは他のモジュールと同様のモジュールとして実装されているため, C は次のようになり BEGIN { require myint; myint->import(); } C は次のようになります. BEGIN { require myint; myint->unimport(); } 従って C 及び C ルーチンはユーザのコードの B<コンパイル時> に呼び出されます. ユーザプラグマは自身の状態をマジカルハッシュ C<%^H> に書き出すことで 保存します, なのでこの2つのルーチンではその操作を行っています. C<%^H> に格納されている情報は optree に保存され, 実行時には C 関数で返されるリストのインデックス値 10 で取得できます. 例示したプラグまでは, 取得は C ルーチンにカプセル化 されていて, ユーザスクリプトの中でのプラグマの値を探すために コールフレームを繰り登る回数をパラメータで受け取ります. これはユーザのスクリプトの各行が呼び出されたときに C<$^H{myint}> の値を確定するために C を使っており, それによって オーバーロードされた加算演算を実装しているサブルーチンに対して 適切なセマンティクスを提供しています. =head1 実装の詳細 optree はスレッド間で共有されています. これは optree がそれを 作った特定のスレッドよりも長生きである(つまりインタプリタの インスタンスよりも)ことを意味し, そして実際に Perl のスカラは optree に格納することはできません. 代わりにコンパクト形式が使われて います, これは整数(符号付及び符号なし), 文字列 若しくは C のみを格納することができます - リファレンスやポインタ値は文字列化 されます. もし複数の値や複雑な構造を保存したいときには例えばC 等でシリアライズする必要があります.C<%^H> からのハッシュキーの 削除は記録され, C 値を持っている存在するキーとは C によって区別できます. =head1 和訳 山科 氷魚 (YAMASHINA Hio) 原典: perl VERSION 5.9.4. 翻訳日: 2007-06-23.