目次 TABLE OF CONTENTS
perlpragma - ユーザプラグマの書き方 perlpragma - how to write a user pragma
プラグマとは, strict や warnings といったような, Perl の
コンパイル時若しくは実行時のある状況に影響を与えるモジュールのことです.
Perl 5.10 ではもう組み込みのプラグマだけに制限されません; レキシカル
スコープでユーザ機能の振る舞いを偏光するユーザプラグマを作成することが
できます.
A pragma is a module which influences some aspect of the compile time or run
time behaviour of Perl, such as strict or warnings. With Perl 5.10 you
are no longer limited to the built in pragmata; you can now create user
pragmata that modify the behaviour of user functions within a lexical scope.
例えば, 算術演算のオーバーロードを行うクラスを作る必要があり,
それを以下のように use integer; 風に提供したいとします.
For example, say you need to create a class implementing overloaded
mathematical operators, and would like to provide your own pragma that
functions much like use integer; You'd like this code
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";
対応する出力: to give the output
A: 4.6
B: 4
C: 4.6
D: 4
E: 4.6
つまり, use myint; の影響下にある場所では加算は整数で行われ,
一方デフォルトではそうではなく(浮動小数点でもおこなわれる),
no myint; を使うことでデフォルトの振る舞いに戻すことも出来ます.
i.e., where use myint; is in effect, addition operations are forced
to integer, whereas by default they are not, with the default behaviour being
restored via no myint;
MyMaths パッケージの最小の実装は次のようになるでしょう:
The minimal implementation of the package MyMaths would be something like
this:
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;
ユーザプラグマ myint を空のリスト () でロードすることで
その import が呼び出されないようにしています.
Note how we load the user pragma myint with an empty list () to
prevent its import being called.
Perl のコンパイル時の動作は myint パッケージに対して作用します:
The interaction with the Perl compilation happens inside package myint:
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;
プラグマは他のモジュールと同様のモジュールとして実装されているため,
use myint; は次のようになり
As pragmata are implemented as modules, like any other module, use myint;
becomes
BEGIN {
require myint;
myint->import();
}
no myint; は次のようになります.
and no myint; is
BEGIN {
require myint;
myint->unimport();
}
従って import 及び unimport ルーチンはユーザのコードの
コンパイル時 に呼び出されます.
Hence the import and unimport routines are called at compile time
for the user's code.
ユーザプラグマは自身の状態をマジカルハッシュ %^H に書き出すことで
保存します, なのでこの2つのルーチンではその操作を行っています.
%^H に格納されている情報は optree に保存され, 実行時には
caller() 関数で返されるリストのインデックス値 10 で取得できます.
例示したプラグまでは, 取得は in_effect ルーチンにカプセル化
されていて, ユーザスクリプトの中でのプラグマの値を探すために
コールフレームを繰り登る回数をパラメータで受け取ります.
これはユーザのスクリプトの各行が呼び出されたときに $^H{myint}
の値を確定するために caller() を使っており, それによって
オーバーロードされた加算演算を実装しているサブルーチンに対して
適切なセマンティクスを提供しています.
User pragmata store their state by writing to the magical hash %^H,
hence these two routines manipulate it. The state information in %^H is
stored in the optree, and can be retrieved at runtime with caller(), at
index 10 of the list of returned results. In the example pragma, retrieval
is encapsulated into the routine in_effect(), which takes as parameter
the number of call frames to go up to find the value of the pragma in the
user's script. This uses caller() to determine the value of
$^H{myint} when each line of the user's script was called, and
therefore provide the correct semantics in the subroutine implementing the
overloaded addition.
optree はスレッド間で共有されています. これは optree がそれを
作った特定のスレッドよりも長生きである(つまりインタプリタの
インスタンスよりも)ことを意味し, そして実際に Perl のスカラは
optree に格納することはできません. 代わりにコンパクト形式が使われて
います, これは整数(符号付及び符号なし), 文字列 若しくは undef
のみを格納することができます - リファレンスやポインタ値は文字列化
されます. もし複数の値や複雑な構造を保存したいときには例えばpack
等でシリアライズする必要があります.%^H からのハッシュキーの
削除は記録され, undef 値を持っている存在するキーとは exists
によって区別できます.
The optree is shared between threads. This means there is a possibility that
the optree will outlive the particular thread (and therefore the interpreter
instance) that created it, so true Perl scalars cannot be stored in the
optree. Instead a compact form is used, which can only store values that are
integers (signed and unsigned), strings or undef - references and
floating point values are stringified. If you need to store multiple values
or complex structures, you should serialise them, for example with pack.
The deletion of a hash key from %^H is recorded, and as ever can be
distinguished from the existence of a key with value undef with
exists.
山科 氷魚 (YAMASHINA Hio) <hio@hio.jp>
原典: perl VERSION 5.9.4. 翻訳日: 2007-06-23. Origlnal distribution is perl VERSION 5.9.4. Translated at 2007-06-23.