Perlの例外が5.14以降で変わった話
詳しくは、このページを見て、”例外処理”で検索するのがいいと思います。
perldelta – perl v5.14.0 での変更点 – perldoc.jp
でも、読んでも分からないので、手を動かしてみます。
Hokkaido.pm Casual#16では、Perl 5.12とPerl 5.16を切り替えながら、
Try::Liteのv0.0.2を使って実演したのですが、
新しく出たTry::Liteのv0.0.3では例の問題を吸収してくれているので、
積極的に使っていきたい所存です。
それはそうと、まずPerlで例外処理の復習から。
use strict; use warnings; my $a = 0; my $b; eval { $b = print 2 / $a; }; if ( $@ ) { print "oops!\n$@"; } else { print $b, "\n"; }
これを実行すると、こんな感じ。
$ perl aaa.pl
oops!
Illegal division by zero at aaa.pl line 7.
見ての通り、0で割ってる訳ですが、
もし、eval{...};
で括らないと、例外が起きて実行が中断されます。
では、eval{...};
を取り除いてみます。
use strict; use warnings; my $a = 0; my $b = print 2 / $a; print "here!\n"; print $b, "\n";
こんな感じですね。
$ perl bbb.pl
Illegal division by zero at bbb.pl line 5.
残念ながら、5行目で中断されてしまいました。
そこで、最初に紹介したコードでは、
例外が発生する可能性のある部分をeval{...};
で括ってあげて、
例外が起きてれば、その旨が入っているであろう$@
をチェックして、
例外が起きた場合は、その旨を表示してた訳です。
で、やっとタイトルの件です。
まずは、こんな感じのコードを用意します。
use strict; use warnings; my $e = ''; eval { local $@; eval { die 'oops!'; }; $e = $@; die $@; }; if ( $@ ) { print "\$@ = $@"; } if ( $e ) { print "\$e = $e"; }
自分の場合はperlbrewを使っているので、こんな感じで実行します。
$ perlbrew switch-off
perlbrew is switched off.
$ perl ccc.pl
$e = oops! at ccc.pl line 8.
手元の環境だと、Perlは5.12.3でした。
次に、いつも使ってるPerlに戻します。
$ perlbrew switch perl-5.16
$ perl ccc.pl
$@ = oops! at ccc.pl line 8.
$e = oops! at ccc.pl line 8.
という訳で、local $@;
することで、
$@
を上書きされたくないケースでもあるのかなーって思いつつも、
local
よく分かってないし、そういうケースに遭遇したことないので、
Perlのバージョンでこういう差異があることがあるよ!程度に覚えておこうと思います。
おしまい。
Leave a Comment