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
.
Я бы предположил, что общие обходные пути включают в себя оценку «ключей HASH» или «значений HASH» –