エラーメッセージを表示させるのに一番よく見かけるのが "warn" と "die" である。
それに追随して、PerlのCoreModule(*1)の Carp もよく使われているようである。
このモジュールは、簡潔にまとめると、「よりユーザー・開発者に分かりやすいエラーメッセージを提供する」ためのものである。サブルーチンの呼び出し履歴(バックスタックトレース)を付けてくれる、などである。
今回示すような簡単なコードピースでは違いは表面化しないのかも知れない。実際、carp(or croak)も、cluck(or confess)も、全く同じ結果になってしまった。厳密には、上記perldocで記述されているが以下のような違いがあるらしい。
・・・よく分からないので、将来のリベンジとして残しておく。
正直なところ、英辞郎などを引いてみても、細かいニュアンスの差になってしまい区別が付かなかった・・・。
#!/usr/bin/perl
use strict;
use warnings;
use Carp;
# "warn"発生時のシグナルハンドラ
sub w01 {
print "======= WARN SIGNAL HANDLER\n";
my ($msg) = @_;
print $msg, "\n";
}
$SIG{__WARN__} = \&w01;
# "die"発生時のシグナルハンドラ
sub d01 {
print "======= DIE SIGNAL HANDLER\n";
my ($msg) = @_;
print $msg, "\n";
}
$SIG{__DIE__} = \&d01;
sub f01 { &f02(); }
sub f02 { &f03(); }
sub f03 {
carp("OOPS!!");
#croak("OOPS!!");
};
eval { &f01(); };
if ($@) {
print '------- $@ is caught', "\n";
warn $@;
}
$ ./carp01.pl
======= WARN SIGNAL HANDLER
OOPS!! at ./carp01.pl line 32
main::f03() called at ./carp01.pl line 28
main::f02() called at ./carp01.pl line 24
main::f01() called at ./carp01.pl line 37
eval {...} called at ./carp01.pl line 36
$ ./carp01.pl
======= DIE SIGNAL HANDLER
OOPS!! at ./carp01.pl line 33
main::f03() called at ./carp01.pl line 28
main::f02() called at ./carp01.pl line 24
main::f01() called at ./carp01.pl line 37
eval {...} called at ./carp01.pl line 36
------- $@ is caught
======= WARN SIGNAL HANDLER
OOPS!! at ./carp01.pl line 33
main::f03() called at ./carp01.pl line 28
main::f02() called at ./carp01.pl line 24
main::f01() called at ./carp01.pl line 37
eval {...} called at ./carp01.pl line 36
warnとdieを処理する、特別なシグナル処理、 $SIG{__WARN__}, $SIG{__DIE__} を使用し、本当にdie相当/warn相当が処理されているのかを確認してみる。その結果 carp を用いると、確かにwarn用のシグナルハンドラが走っていることがわかる。また、croakの場合、一度die用のシグナルハンドラが走ってから(これ自体はdie相当ということで問題ない)、 $@がセットされる ため、下のwarn処理に走り、それにより今度はwarn用のシグナルハンドラが走っている。
続いて carp, croak を cluck, confessに変えてみる。コードピースは省略する。
$ ./carp01.pl
======= WARN SIGNAL HANDLER
OOPS!! at ./carp02.pl line 32
main::f03() called at ./carp02.pl line 28
main::f02() called at ./carp02.pl line 24
main::f01() called at ./carp02.pl line 37
eval {...} called at ./carp02.pl line 36
$ ./carp01.pl
======= DIE SIGNAL HANDLER
OOPS!! at ./carp02.pl line 33
main::f03() called at ./carp02.pl line 28
main::f02() called at ./carp02.pl line 24
main::f01() called at ./carp02.pl line 37
eval {...} called at ./carp02.pl line 36
------- $@ is caught
======= WARN SIGNAL HANDLER
OOPS!! at ./carp02.pl line 33
main::f03() called at ./carp02.pl line 28
main::f02() called at ./carp02.pl line 24
main::f01() called at ./carp02.pl line 37
eval {...} called at ./carp02.pl line 36
このように、carp/croakと出力に差異は見られなかった。 恐らく簡単なコードピースではこの差異は表に出てこないと思われる。
とはいえ、cluck/confessでも、warn相当/die相当でシグナルハンドラが処理されていることを確認できた。