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で表示しています。
作ってる最中にひどく簡単なところに、うっかりはまって、内部メソッドのテストもちゃんと書かなきゃなぁ...って痛感しました。
テスト書いとけば、寝ぼけてても、気付ける。