tieでモジュール作るの初めてなんですが、Tie::Trace作ってみました。
0.04が最新ですが、まだCPANにインデックスされていないかも。
ある変数にどんな値が入れられていくのかを追えるものです。デバッガが面倒な時もあるってことで。使いこなしてないだけ?と言われるとその通りですが(ぉ
リファレンスが入ってきた場合は、その中を再帰的にチェックして、そのリファレンスの中に何かが入った場合も追えます(追わないことも可)。ただし、blessされているリファレンスや、tieされている変数は無視します。blessed ref は大丈夫な気がするんだけど、なんかうまくいかなかったんで。
ハッシュだったら、あるキーだけとか。その他でも、ある値だけとか、ある正規表現にマッチするものとか、コードリファレンスで真が帰ってくる場合のみとか指定できます。
基本は caller(1) の場所を教えてくれますが、どこまで遡るかの指定ができます。複数の指定もできます。
詳しくはドキュメントを...英語壊れ気味だけど、日本語もあるので...ただ英語を元に書いたら日本語も壊れ気味(ぉ
サンプルスクリプト。
#!/usr/bin/perl
use Tie::Trace;
use CGI;
{
print "Test 1 /////////////\n";
tie my %hash, "Tie::Trace";
test(\%hash);
}
{
print "\n\nTest 2 /////////////\n";
tie my %hash, "Tie::Trace", caller => [1 .. 5], debug => 'dumper';
test(\%hash);
}
{
print "\n\nTest 3 /////////////\n";
tie my %hash, "Tie::Trace", use => ['scalar'], caller => [1 .. 5], debug => sub{my($self) = @_; Data::Dumper::Dumper($self->parent ? $self->parent->storage : () );};
test(\%hash);
}
sub test{
my $hash = shift;
my $s;
my $x = { hash => 1, array => [qw/a b c d e/], scalar => \$s,};
$hash->{1} = $x;
$hash->{1}->{hash} = 3;
${$x->{scalar}} = "0000";
push(@{$hash->{1}->{array}}, "array", "array2");
${$hash->{1}->{scalar}} = 10;
subroutine($hash, "hogehoge");
}
sub subroutine{
subroutine2(@_);
}
sub subroutine2{
my($r_hash, $value) = @_;
$r_hash->{hogehogehoge} = $value;
}これを実行すると、下記のように表示表示されます。
Test 1 /////////////
Hash => Key: 1, Value: HASH(0x82b5820) at /home/ktat/scripts/tie-debug.pl line 29.
Hash => Key: hash, Value: 3 at /home/ktat/scripts/tie-debug.pl line 30.
Scalar => Value: 0000 at /home/ktat/scripts/tie-debug.pl line 32.
Array => Point: 5, Value: array at /home/ktat/cvs/modules/Tie-Trace/lib/Tie/Trace.pm line 229.
Array => Point: 6, Value: array2 at /home/ktat/cvs/modules/Tie-Trace/lib/Tie/Trace.pm line 229.
Scalar => Value: 10 at /home/ktat/scripts/tie-debug.pl line 36.
Hash => Key: hogehogehoge, Value: hogehoge at /home/ktat/scripts/tie-debug.pl line 47.
Test 2 /////////////
Hash => Key: 1, Value: $VAR1 = {
'scalar' => \undef,
'array' => [
'a',
'b',
'c',
'd',
'e'
],
'hash' => 1
};
at /home/ktat/scripts/tie-debug.pl line 15.
Hash => Key: hash, Value: $VAR1 = 3;
at /home/ktat/scripts/tie-debug.pl line 15.
Scalar => Value: $VAR1 = '0000';
at /home/ktat/scripts/tie-debug.pl line 15.
Array => Point: 5, Value: $VAR1 = 'array';
at /home/ktat/scripts/tie-debug.pl line 34.
at /home/ktat/scripts/tie-debug.pl line 15.
Array => Point: 6, Value: $VAR1 = 'array2';
at /home/ktat/scripts/tie-debug.pl line 34.
at /home/ktat/scripts/tie-debug.pl line 15.
Scalar => Value: $VAR1 = 10;
at /home/ktat/scripts/tie-debug.pl line 15.
Hash => Key: hogehogehoge, Value: $VAR1 = 'hogehoge';
at /home/ktat/scripts/tie-debug.pl line 42.
at /home/ktat/scripts/tie-debug.pl line 38.
at /home/ktat/scripts/tie-debug.pl line 15.
Test 3 /////////////
Scalar => Value: $VAR1 = {
'scalar' => \'0000',
'array' => [
'a',
'b',
'c',
'd',
'e'
],
'hash' => 3
};
at /home/ktat/scripts/tie-debug.pl line 21.
Scalar => Value: $VAR1 = {
'scalar' => \10,
'array' => [
'a',
'b',
'c',
'd',
'e',
'array',
'array2'
],
'hash' => 3
};
at /home/ktat/scripts/tie-debug.pl line 21.Test 1, 2, 3 とも、オプション変えただけで、一緒のテストをしていますが、出力がいろいろと違います。
1番目は何のオプションもなしです。
2番目はvalueの値をData::Dumper::Dumperで出すようにしているのと、callerで遡る数を指定しています。
3番目は2番目に加えて、scalarに値が入れられた場合のみにしぼり、debugにコードリファレンスを指定し、親のリファレンスの中身をData::Dumper::Dumperで表示しています。
作ってる最中にひどく簡単なところに、うっかりはまって、内部メソッドのテストもちゃんと書かなきゃなぁ...って痛感しました。
テスト書いとけば、寝ぼけてても、気付ける。