私はeach
Perlハッシュを反復処理するために使用しています:
while (my ($key,$val) = each %hash) {
...
}
それから何か面白いことが起こり、ハッシュを印刷したいと思います。最初、私は次のようなことを考えます。
while (my ($key,$val) = each %hash) {
if (something_interesting_happens()) {
foreach my $k (keys %hash) { print "$k => $hash{$k}\n" }
}
}
しかし、それは機能しません。ハッシュでkeys
(または)を呼び出すと、に使用される内部イテレータがリセットされることを誰もが知っているため、無限ループが発生する可能性があります。たとえば、これらのスクリプトは永久に実行されます。values
each
perl -e '%a=(foo=>1); while(each %a){keys %a}'
perl -e '%a=(foo=>1); while(each %a){values %a}'
問題ないと思いました。ハッシュのコピーを作成し、そのコピーを印刷することができました。
if (something_interesting_happens()) {
%hash2 = %hash;
foreach my $k (keys %hash2) { print "$k => $hash2{$k}\n" }
}
しかし、それもうまくいきません。each
これにより、イテレータもリセットされます。実際、リストコンテキストでを使用すると、イテレータ%hash
がリセットされるようです。each
したがって、これらも永久に実行されます。
perl -e '%a=(foo=>1); while(each %a){%b = %a}'
perl -e '%a=(foo=>1); while(each %a){@b = %a}'
perl -e '%a=(foo=>1); while(each %a){print %a}'
これはどこかに文書化されていますか?perlがハッシュの内容をリターンスタックにプッシュするために同じ内部イテレータを使用する必要があるかもしれないことは理にかなっていますが、それを行う必要がなかったハッシュ実装も想像できます。
さらに重要なことに、私がやりたいことをする方法はありますか?each
イテレータをリセットせずにハッシュのすべての要素にアクセスするには?
each
これは、イテレーション内でハッシュをデバッグできないことも示唆しています。次の場所でデバッガーを実行することを検討してください。
%a = (foo => 123, bar => 456);
while ( ($k,$v) = each %a ) {
$DB::single = 1;
$o .= "$k,$v;";
}
print $o;
デバッガーが停止するハッシュを検査するだけで(たとえば、p %a
またはを入力x %a
)、プログラムの出力を変更します。
更新:Hash::SafeKeys
この問題の一般的な解決策としてアップロードしました。私を正しい方向に向けてくれた@gpojdと、解決策をはるかに簡単にする提案をしてくれた@cjmに感謝します。