each()は遅い上に微妙な問題も起きやすい

特別な条件がないかぎり、each()は使うべきではありません。代わりにkeys()/values()を使うべきです。その理由は2つあります。

each()は遅い

each()でハッシュ全体をループするのは遅いです。これは、keys()/values()がその内部の値をそのまま参照する*1のに対し、each()は代入しないとその値を使えないからです。
ベンチマーク

#!perl
use strict;
use warnings;
use Benchmark qw(cmpthese);

my %hash = map { $_ => $_ } ( 1 .. 10000 );

cmpthese -1, {
    each_k => sub {
        while(my $key = each %hash) { }
    },
    each_kv => sub {
        while(my($key, $value) = each %hash) { }
    },
    keys => sub {
        foreach my $key(keys %hash) { }
    },
    values => sub {
        foreach my $value(values %hash) { }
    },
};
__END__

結果*2:

$ perlbrew exec perl each-bench.pl
perl-5.12.3
==========
          Rate each_kv  each_k    keys  values
each_kv 57.1/s      --    -20%    -56%    -81%
each_k  71.7/s     25%      --    -44%    -77%
keys     129/s    126%     80%      --    -58%
values   307/s    438%    329%    138%      --


perl-5.14.0
==========
          Rate each_kv  each_k    keys  values
each_kv 57.7/s      --    -20%    -55%    -79%
each_k  71.7/s     24%      --    -44%    -74%
keys     128/s    121%     78%      --    -53%
values   274/s    375%    282%    115%      --


perl-5.8.9
==========
          Rate each_kv  each_k    keys  values
each_kv 55.4/s      --    -21%    -57%    -83%
each_k  70.3/s     27%      --    -46%    -79%
keys     130/s    134%     85%      --    -60%
values   328/s    492%    367%    153%      --

ラクダ本などでは「膨大な数のエントリを持つtieされたハッシュ(DBMなど)でkeys()/values()を行うとメモリを大量に消費するからeach()を使うほうが空間効率が良い」との記述がありますが、これは特殊なケースです。時間効率の観点からみるとeach()を使う理由はありません。

each()ループを中断すると内部イテレータの不整合が起きる

each()はハッシュ毎に内部イテレータを使用してループを行いますが、これはループをlast()などで中断してもリセットされません。リセットするためには明示的にkeys()/values()を呼び出す必要があります。

# linear search
my $found;
while( my $k = each %hash) {
    if($k eq 'foo') {
        $found = $k;
        last;
    }
}
keys %hash; # reset its internal iterator

この内部イテレータの不整合によって非常に分かりにくいバグを生むことが知られています。私も何度かそういったバグを経験しましたし、Perlレベルではなるべくeach()を避けたほうがいいでしょう*3

追記:

*1:`foreach my $v(each %h){ $v++ }` すると%hの値も変化する。keys()の場合は直接内部の値そのものではないが、それでも内部の値から効率のいい方法で新しい値を生成するので、values()よりは遅いがeach()よりは速い。

*2:複数バージョンの比較をしているが、速度の違いがバージョンの違いを表しているわけではない。バイナリごとのビルドオプションが異なるからである。

*3:XSレベルではkeys()/values()がなくeach()相当しかないため、テストを慎重に行う他ない。