Perl-users.jp

変態モジュール総覧

Perl の世界には、「変態モジュール」と呼ばれるモジュールがたくさん存在します。

これらは、モジュールの形態をとりながら、Perl の内部に踏み込み、蹂躙しているという恐ろしい存在です。 しかしながら、これらのモジュールは使いどころを間違えなければ非常に有用であり、あなたのプログラムに無限の可能性をもたらすことでしょう。 自分の足をどうやって撃ちぬくか、よく考えてからつかってください。

下記のモジュールたちは、それ自体が変態的なものもあれば、変態的なことをするときに使うモジュールもあります。

PadWalker

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 のようなモジュールが作れます。

Lexical::Persistence

レキシカル変数を永続的な変数にします。

下記のようなコードが動くようになります。

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 に依存しています。

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

Sub::Name を使うと、コードリファレンスに名前をつけることができます。 anonymous coderef に名前を与えることも可能になります。 これにより、stacktrace を見やすくすることができます。

use Sub::Name;
subname 'foo', sub { };

Devel::GlobalDestruction

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();
}

Scope::Guard

スコープからぬけるときに実行される coderef を定義できます。

Devel::Gladiator

Perl の内部におけるメモリの具合をみることができます。メモリリークをみつけたり、メモリ使用状況をプロファイリングするのに使えます。

autobox

Perl のプリミティブな型をオブジェクトかのように扱えます。PL_check をハックしていて、反則ぎりぎりですが、使いどころをまちがえなければ有用です。

my $range = 10->to(1); # [ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]

macro.pm

Perl でマクロっぽいことができます。

use macro my_if => sub{ $_[0] ? $_[1] : $_[2] };
my_if( 0, say('true'), say('false') ); # only 'false' is printed

Data::Thunk

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 $