Perl の世界には、「変態モジュール」と呼ばれるモジュールがたくさん存在します。
これらは、モジュールの形態をとりながら、Perl の内部に踏み込み、蹂躙しているという恐ろしい存在です。 しかしながら、これらのモジュールは使いどころを間違えなければ非常に有用であり、あなたのプログラムに無限の可能性をもたらすことでしょう。 自分の足をどうやって撃ちぬくか、よく考えてからつかってください。
下記のモジュールたちは、それ自体が変態的なものもあれば、変態的なことをするときに使うモジュールもあります。
PadWalker は変態モジュールの筆頭です。レキシカルスコープの変数を、レキシカルスコープの外から見たり書き換えたりできます。 peek_my peek_our peek_sub closed_over という4つの関数をサポートしています。
下記のようなありえない操作を可能にしてくれます。
sub increment_my_x {
my $h = peek_my(1);
${ $h->{'$x'} }++;
}
my $x = 5;
increment_my_x;
print $x; # prints 6
このモジュールを使うと、String::TT のようなモジュールが作れます。
レキシカル変数を永続的な変数にします。
下記のようなコードが動くようになります。
use Lexical::Persistence;
my $lp = Lexical::Persistence->new();
$lp->call( \&setter );
$lp->call( \&getter );
sub setter { my $x = "some value" }
sub getter { print my $x, "\n" }
このモジュールは PadWalker と Devel::LexAlias に依存しています。
他のスコープにレキシカル変数を export できます。
use Devel::LexAlias qw(lexalias);
sub steal_my_x {
my $foo = 1;
lexalias( 1, '$x', \$foo );
}
sub foo {
my $x = 22;
print $x; # prints 22
steal_my_x;
print $x; # prints 1
}
Sub::Name を使うと、コードリファレンスに名前をつけることができます。 anonymous coderef に名前を与えることも可能になります。 これにより、stacktrace を見やすくすることができます。
use Sub::Name;
subname 'foo', sub { };
Perl には、インタープリタ終了時に global destruction というゴミ収集フェーズが存在します。 global destruction においては、オブジェクト回収の順番が微妙なので、なんか変な状態になります。 この問題により、Perl ではデストラクタ(DESTROY)を正しく実装するのが困難です。
この問題を解決するのが Devel::GlobalDestruction です。このモジュールを使うと、global destruction 状態に あるかどうかを簡単に判別することができます。
use Devel::GlobalDestruction;
sub DESTROY {
return if in_glboal_destruction();
do_somthing_a_little_tricky();
}
スコープからぬけるときに実行される coderef を定義できます。
Perl の内部におけるメモリの具合をみることができます。メモリリークをみつけたり、メモリ使用状況をプロファイリングするのに使えます。
Perl のプリミティブな型をオブジェクトかのように扱えます。PL_check をハックしていて、反則ぎりぎりですが、使いどころをまちがえなければ有用です。
my $range = 10->to(1); # [ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]
Perl でマクロっぽいことができます。
use macro my_if => sub{ $_[0] ? $_[1] : $_[2] };
my_if( 0, say('true'), say('false') ); # only 'false' is printed
Perl で遅延評価を実現します。
use Data::Thunk qw(lazy);
my %hash = ( foo => lazy { $expensive }, );
$hash{bar}{gorch} = $hash{foo};
$hash{bar}{gorch}->foo; # vivifies the object
warn overload::StrVal($hash{foo}); # replaced with the value
変態モジュールを探すには、変態っぽい人のモジュール一覧から探すのが簡単です。
Last modified: $Date: 2008-06-24T14:20:57.955997Z $