2

No idea why this script runs infinitely. It looks fine to me.


while (my ($k, $v) = each (%ENV)){
 my @k = keys (%ENV);
 if($k eq $k[0]){
   print "ok";
  }
}
4

3 回答 3

12

keys以及values)函数重置函数使用的迭代器each。由于密钥不会改变,您可以在循环之外检索它们。

于 2013-08-21T19:53:39.863 回答
9

在循环内调用keys会重置each. 不要那样做。这应该有效:

my @k = keys (%ENV);
while (my ($k, $v) = each (%ENV)){
 if($k eq $k[0]){
   print "ok";
  }
}
于 2013-08-21T19:53:45.977 回答
0

其他人已经回答了主要问题,但是我想警告不要使用 while-each-loop 来迭代哈希。如果你想处理整个哈希,我建议不要使用这个结构:

while (my ($k, $v) = each %HASH) {
}

为什么?此循环将从散列迭代器留在 %HASH 中的当前位置开始。如果哈希迭代器不在开头,那么这将只处理一部分哈希而不是整个哈希。例子:

use strict;
use warnings;

# demonstrate hash iterator behaviour with each():
sub somefunc {
    my ($test_ref, $string) = @_;
    while (my ($k, $v) = each %$test_ref) {
            if ($k eq $string){
                    print "$string found\n";
                    return;
            }
    }
    print "$string not found\n";
}

my %test = (
    foo => 'a',
    bar => 'b'
);

somefunc(\%test, 'foo');
somefunc(\%test, 'foo');

这将打印:

foo found
foo not found

我曾经使用 while-each-loop 来检查深度嵌套数据结构中的一些值。然后我使用 return 或 last 退出循环。这使哈希迭代器悬在我检查的最后一个位置。很久以后,在不同的模块中,在不同的函数中,我再次使用 while-each-loop 继续处理哈希,假设它将处理整个哈希。然而,它在散列迭代器的最后一个位置继续,只处理散列的其余部分。这是一个很难找到的错误。

如果你想使用 each() 来处理整个散列,你应该总是在它前面加上键 %HASH。例子:

keys %HASH; # keys will reset the hash iterator
while (my ($k, $v) = each %HASH) { # will really process the ENTIRE hash
}

上面的 Mark Reeds 示例也将始终有效,因为他在执行 while-each-loop 之前调用了键 %ENV。通过他对keys()的使用,哈希迭代器被重置,因此while-each-loop将处理整个哈希。

于 2014-01-03T12:09:10.973 回答