Perlで例外処理

とりあえず、手を動かして覚えることにした。
で、記事を書こうと思ったら、すでに良い感じの記事が存在するので、
それらを紹介しようと思う。

perl – use Carp; # warn() と die() だけじゃなくて – 404 Blog Not Found
http://blog.livedoor.jp/dankogai/archives/51073468.html

perlの例外処理のこと – cipher
http://ash.roova.jp/cipher/2013/08/perl-5182.html

という訳なので、Try::Liteを使ってみようと思う。
詳しくは、以下をどうぞ。

Try::Lite 「より安全な例外キャッチを簡単に」 – YappoLogs
http://blog.yappo.jp/yappo/archives/000804.html

use strict;
use warnings;
use v5.10;

use Try::Lite;

my $file = 'not-exists.txt';
my $fp;

try {
    open( $fp, '<', $file )
        or die "Cannot open < $file. :$!";
} (
    '*' => sub {
        say '--- for any exception ---';
        say $@;
    }
);

実行結果は、こんな感じ。
$ perl aaa.pl
--- for any exception ---
Cannot open < not-exists.txt. :No such file or directory at aaa.pl line 11.

こんな感じで、エラーをキャッチできる。
$!がなんなのか分からなかったけど、
この辺を読んでなんとなく理解した。

perlvar – Perl で定義済みの変数 – perldoc.jp
http://perldoc.jp/docs/perl/5.16.1/perlvar.pod

なので、$!はエラーが起きた直後に確保する必要がある。
そこで、任意のエラーメッセージと$!を分けて確保する方法を考えてみる。

極端な例を上げるならこんな感じ。

use strict;
use warnings;
use v5.10;

use Try::Lite;

my $file = 'not-exists.txt';
my $fp;

try {
    open( $fp, '<', $file )
        or die [ "Cannot open < $file.", $! ];
} (
    '*' => sub {
        say '--- for any exception ---';
        say join "\n", @{$@};
    }
);

そして、結果はこんな感じ。
$ perl bbb.pl
--- for any exception ---
Cannot open < not-exists.txt.
No such file or directory

あと、このモジュールを使うとこういう風にも書ける。

package Exception;
use strict;
use warnings;

sub new {
    my ( $pkg, $msg ) = @_;
    bless { msg => $msg }, $pkg;
}

package Foo;
use strict;
use warnings;
use parent -norequire, 'Exception';

package main;
use strict;
use warnings;
use v5.10;

use Try::Lite;

catch_test( Exception->new('This is Exception.') );
catch_test( Foo->new('This is Foo.') );
catch_test( 'This is string.' );

say '=== End of Script ===';

sub catch_test {
    my $ex = shift;

    try {
        die $ex;
    } (
        'Exception' => sub {
            say $@->{msg};
        },
        '*' => sub {
            say $@;
        }
    );
}

実行結果は、こんな感じ。
$ perl ccc.pl
This is Exception.
This is Foo.
This is string. at ccc.pl line 32.

=== End of Script ===

これだと、例外オブジェクトがFooの場合、
継承してるクラスを見て判断してくれるので、
'Foo' => sub { ... }を用意する必要もないし、
blessしてない例外も捕捉できて便利。

おしまい。

Leave a Comment