each 有一个内置的、隐藏的全局变量,它会伤害你。除非您需要这种行为,否则只使用keys 会更安全。
考虑这个我们想要对 k/v 对进行分组的示例(是的,我知道 printf 会做得更好):
#!perl
use strict;
use warnings;
use Test::More 'no_plan';
{ my %foo = map { ($_) x 2 } (1..15);
is( one( \%foo ), one( \%foo ), 'Calling one twice works with 15 keys' );
is( two( \%foo ), two( \%foo ), 'Calling two twice works with 15 keys' );
}
{ my %foo = map { ($_) x 2 } (1..105);
is( one( \%foo ), one( \%foo ), 'Calling one twice works with 105 keys' );
is( two( \%foo ), two( \%foo ), 'Calling two twice works with 105 keys' );
}
sub one {
my $foo = shift;
my $r = '';
for( 1..9 ) {
last unless my ($k, $v) = each %$foo;
$r .= " $_: $k -> $v\n";
}
for( 10..99 ) {
last unless my ($k, $v) = each %$foo;
$r .= " $_: $k -> $v\n";
}
return $r;
}
sub two {
my $foo = shift;
my $r = '';
my @k = keys %$foo;
for( 1..9 ) {
last unless @k;
my $k = shift @k;
$r .= " $_: $k -> $foo->{$k}\n";
}
for( 10..99 ) {
last unless @k;
my $k = shift @k;
$r .= " $_: $k -> $foo->{$k}\n";
}
return $r;
}
在实际应用程序中调试上述测试中显示的错误将非常痛苦。 (为了获得更好的输出,请使用 Test::Differences eq_or_diff 而不是 is。)
当然one() 可以通过使用keys 清除子程序开始和结束处的迭代器来修复。如果你记得。如果你所有的同事都记得。只要没有人忘记就绝对安全。
我不了解你,但我会坚持使用 keys 和 values。