doはブロックだけどevalはブロックじゃないよ

Perlのブロックってすごいよね. パッと見, 構造っぽいもん. でもevalとかdoとかってブロックが後に続いているだけなんだよね(微妙な認識かも)?

ブロック - make for h @ppy_things;

タイトルで言ってしまった感がありますが^^;

厳密に言うとdoとevalのブロックは違うんですよ。以下のコード結果を見れば一発。

sub do_func {
    do {
        return 'block return';
    };
    return 'normal return';
}

sub eval_func {
    eval {
        return 'block return';
    };
    return 'normal return';
}

print do_func(),"\n";   # block return
print eval_func(),"\n"; # normal return

returnは関数から離脱するためのものですが、eval_funcの方はなぜか「normal return」の方が帰ってます。

returnは関数から離脱するためのも。そう、とどのつまり、evalのブロックが関数扱いだから「block return」はevalの戻り値として帰っちゃったわけなのです。

sub eval_func {
    my $ret = eval {
        return 'block return';
    };

    print $ret; # block return

    return 'normal return';
}

Error.pmのtryとかも、結局のところ引数に関数のリファレンスを受け取ってるだけなんですよね。

sub my_try {
    my $code = shift;
    $code->();
}

my_try( sub {
    return 'hoge';
} );

でプロトタイプ宣言することでsubの部分を省略できるんだ。

sub my_try (&) {
    my $code = shift;
    $code->();
}

my_try {
    return 'hoge';
};

あたかもブロックに見えるけど実は関数のリファレンスだったというお話でした。

ちゃんちゃん。