だるろぐ

だるいぶろぐです

evalするなら local $@ しよう

$1とか$@とかの特殊変数はグローバルなので、こいつらを使うときはlocal宣言しようと。

package Oya;
use Mouse;

sub hoge {
    eval {die "died"};
    "hoge"
}

1;
use Oya;
use strict;
use warnings;

my $o = Oya->new;

if ($@) {warn "err 1"}
warn $o->hoge;
if ($@) {warn "err 2"}
eval {die "deeeeeeeeeeeeee"};
if ($@) {warn "err 3"}

こんなのを実行すると

% perl m.pl
hoge at m.pl line 8.
err 2 at m.pl line 9.
err 3 at m.pl line 11.

と、使う側でevalしなくても$@が真になってしまうので。
で、何とかするには

package Oya;
use Mouse;

sub hoge {
    local $@;
    eval {die "died"};
    "hoge"
}

1;

と、evalする前に local $@ してやると

% perl m.pl
hoge at m.pl line 8.
err 3 at m.pl line 11.

と平和になると。
常識的に考えてモジュール側でlocal宣言するべきなんですが、宗教上の事情などによりモジュールを書き換えるのに激しい抵抗が有る場合は仕方ないので

if ($@) {warn "err 1"}
warn $o->hoge;
local $@;
if ($@) {warn "err 2"}
eval {die "deeeeeeeeeeeeee"};
if ($@) {warn "err 3"}

と、モジュールを使う側で宣言してやりましょう。


そういやcatalystでも$1とかを使っててちょっとアレな思いをしたことが。
http://d.hatena.ne.jp/foosin/20090113/1231855262
5.7しか使ってないので、5.8で直ってるかは知りません。