クラスメソッドのインポートをModule::Compileでやっちゃう。

ふーむ。

 use Import qw(FormValidator::Simple#check as Validate);

とすると、FormValidator::Simple->check() を呼び出す Validate関数 を定義してくれる Import.pm ってのを考えてみました。

http://www.fs-output.com/rintaro/2007/09/import-class-method.html

もういっそのことコードフィルターにしちゃえー、とか思いついたんだけどどーかな?

ってことでさっそく作ってみた。ネーミングはとりあえずFilter::ClassMethod。

package Filter::ClassMethod;
use strict;
use warnings;
use Module::Compile -base;

sub pmc_compile {
    my ( $class, $source, $extra ) = @_;
    
    my $vars = do {
        ( my $vars = $extra->{use} ) =~ s/^\s*use\s+Filter::ClassMethod\s*//;
        unless ( $vars =~ /;\s*$/ ) {
            $vars .= $1 if $source =~ s/([^;]*);//s;
        }
        eval "$vars";
    };
    die "error evaluating vars on use line ($extra->{use}): $@"
        if $@;
    
    my $funcs = join '|' , sort { $b cmp $a } keys %$vars;
    $source =~ s{(\s*use\s+)?([^A-Za-z0-9:]*)($funcs)([^A-Za-z0-9:]*)}{
        my $use  = $1;
        my $be   = $2;
        my $af   = $4;
        my $func = $3;
        if ( $use ) {
            $use.$be.$func.$af;
        }
        else {
            my $class  = shift @{$vars->{$func}} || die 'class not found.';
            my $method = shift @{$vars->{$func}} || 'new';
            $be."${class}->$method".$af;
        }
    }ge;
    
    return $source;
}

1;

これを使えばあら不思議、

use strict;
use warnings;

use Filter::ClassMethod {
    Validate => [qw/FormValidator::Simple check/],
    Foo      => [qw/Foo/],
};

use FormValidator::Simple;
use CGI;
use Foo;

Validate( CGI->new,[] );

Foo();

このように書くだけで初コンパイル時に置換してくれちゃいます。

しかも単なる置換なので関数呼び出し時のスピードも気にする必要まったく無し!!!


・・・ま、ネタってことで。



追記

コードがちょいミスってたorz

アップした後に間違いに気付く法則。マーフィーってやつ?