[Perl]useなしでどこでもDump(@INCにオブジェクトを格納するパターン)
PERL HACKSを読んでいたら@INCにはhookが仕込めるということが書いてありました。
■[Perl]use無しでどこでも変数をダンプするpackage P;p
でも言及されているとおりかねてからuseがめんどうだと思っていたのですが、これを使えばうまくいくんじゃないか?ということでやってみました。
@INCの仕組み
http://perldoc.perl.org/functions/require.html
によると@INCにはCODEやオブジェクトを格納することができます。
これを利用するとモジュールロード前にhookを仕込むことができます。
There are three forms of hooks: subroutine references,
array references and blessed objects.
とあります。subroutine referencesが簡単ですがどーせならblessed objectsの方がということでこちらでやってみます。
オブジェクトの場合はINCというメソッドを定義するとモジュールをロードするたびにそのメソッドを呼び出してくれます。ただmainパッケージになってしまう(ここがよくわらかなかった)らしいのでパッケージ名をフル指定しないといけないようです。
package P;
use strict;
use YAML;
sub new {
my $class = shift;
return bless { modules => [ @_ ] }, $class;
}
sub import {
my $class = shift;
my (@modules) = @_;
push @modules, split /[,\s]+/msx, $ENV{P} || q{};
unshift @INC, P->new(@modules)
unless (grep {ref $_ eq __PACKAGE__ } @INC);
}
sub p {
my ($package, $file, $line) = caller();
warn "[$file at line $line] " . YAML::Dump(@_);
}
sub P::INC {
my ($self, $module) = @_;
if (my @modules = @{$self->{modules}}) {
return unless ( grep { $module =~ m|^$_| } @modules);
}
(my $mod_name = $module) =~ s|/|::|g;
$mod_name =~ s|\.pm$||;
no strict 'refs';
*{"$mod_name\::p"} = \&p;
return;
}
1;
こんな感じで実装してみました。
pを使う方
package PUser;
use strict;
use base 'Class::Accessor';
sub hoge {
p "Hello Debug P";
p { hoge => 'foo' }, "bar bar";
warn "hoge called";
}
1;
起動ファイル(run_p.pl)
use strict;
use PUser;
PUser->hoge();
これで
とやると全てのパッケージでp関数が利用できます。
perl -MP run_p.pl
0 件のコメント:
コメントを投稿