dieの引数って文字列だけじゃなかったんですね。
こんな風にdieの引数省略したら、見慣れないメッセージが。
% perl eval {die "in eval"; }; die; in eval at - line 1. ...propagated at - line 2.
perldocを見てみます。
If LIST is empty and $@ contains an object reference that has a PROPAGATE method, that method will be called with additional file and line number parameters. The return value replaces the value in $@. i.e. as if $@ = eval { $@->PROPAGATE(__FILE__, __LINE__) }; were called.
If $@ is empty then the string "Died" is used.
へえ。dieの引数って省略できたんですね。しかも、PROPAGATEなんてメソッドも知りませんでした。
die() can also be called with a reference argument. If this happens to be trapped within an eval(), $@ contains the reference.
しかも、dieにリファレンス渡せるなんて。
試しにコード書いてみました。
use strict; use warnings; { package MyException; sub new{ bless \ $_[1], $_[0]; } sub PROPAGATE{ my $self = shift; my ($file, $lineno) = @_; return MyException->new( sprintf('propagated(%s/%d):%s', $file, $lineno, $$self), ); } } eval{ eval { eval{ die MyException->new("first error"); }; print ${$@}, "\n"; die; }; print ${$@}, "\n"; die; }; print ${$@}, "\n"; die;
実行結果は以下。
first error propagated(test.pl/22):first error propagated(test.pl/25):propagated(test.pl/22):first error MyException=SCALAR(0x800e34)
うーん、まあ、意図した通りの動きなんですけど、PROPAGATEの使い道がちょっと思いつかないですね。Java脳だと、単純に$@を別の例外でラップしたくなります。