each
内置一个隐藏的全局变量,可能会对您造成伤害。除非您需要此行为,否则最好只使用 keys
。
考虑以下示例,我们想要分组 k/v 对(是的,我知道 printf
可以更好地完成这项工作):
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
。)
当然,可以通过在子程序的开头和结尾使用keys
清除迭代器来修复one()
函数。只要你记得,并且所有同事都记得,那么这样做是完全安全的。
我不知道你是怎么想的,但我仍然坚持使用keys
和values
。
keys HASH
或values HASH
。 - Daniel LeCheminant