Perlでのエラー処理として一番初めに思いつくのがeval〜if。
#!/usr/bin/perl eval { print 1 / 0; }; if ( $@ ) { die "ouch! : $@"; } # 実行すると # ouch! : Illegal division by zero at 何たら # と表示される。
これはお世辞にもエレガントとはいえない構文なのでいろんな代替策が作られている。
お手軽で、しかも他の言語のようなtry〜catch構文を実現してくれるのはErrorモジュール。
#!/usr/bin/perl use Error qw! :try !; try { print 1 / 0; } catch Error with { my $e = shift; die "ouch! : $e"; }; # 上の例と同じものが表示される。
しかし、この”with”がくせ者である。これが他のモジュールとバッティングしやすいのだ。
#!/usr/bin/perl package Me; use Moose; use Error qw! :try !; sub run { my $self = shift; try { print 1 / 0; } catch Error with { my $e = shift; die "ouch! : $e"; }; } __PACKAGE__->meta->make_immutable; package main; Me->new->run; # compilation errorになる。 # 他には、Win32::OLE::withとのバッティングが痛い!
回避できないこともないのだが、ググっても姑息なものしかないみたい。
use Moose ( with => { -as => "role_with" }, "has", "extends" ); use Error qw! :try !;
そこでerrorsモジュールである。
#!/usr/bin/perl package Me; use Moose; use errors -with_using; sub run { my $self = shift; try { print 1 / 0; } catch Error using { die "ouch! : $@"; }; } __PACKAGE__->meta->make_immutable; package main; Me->new->run; # ちゃんと動く。
errorsモジュールはErrorモジュールを拡張して実装されているので構文はほぼ一緒である。”-with_using”オプションを付けると、”with”の別名として”using”がインポートされるのでMooseの動きを妨げない1。
構文が拡張されているのはそのusing(with)文で、その直後のブロックにはエラーオブジェクトを”$_”及び”$@”に入れたまま渡される。ちょっとだけ見た目がすっきりした。
注意点は、まだまだ開発中のモジュールであること。僕にはあんまり関係ないけどな!
- 本当はこのオプションなしで透過的に実行してくれるはずだが、そこまではまだ実装できていないようだ。 ↩