Reputation: 2673
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";
}
}
Upvotes: 2
Views: 83
Reputation: 85
The main question has been answered by others, i would however like to caution against the use of a while-each-loop for iterating through a hash. If you want to process the entire hash, i would recommend against using this construct:
while (my ($k, $v) = each %HASH) {
}
Why? This loop will start at the current position the hash iterator was left in %HASH. If the hash iterator is not at the beginning, then this will only process a part of the hash and not the entire hash. Example:
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');
This will print:
foo found
foo not found
I once used a while-each-loop for checking some values in a deeply nested data structures. I then exited the loop using return or last. This left the hash iterator dangling at the last position i was checking. Much later, in a different Module, in a different function i then continued to process the hash using again a while-each-loop, assuming it would process the entire hash. It continued however at the last position of the hash iterator, processing only the remainder of the hash. This was a difficult to find bug.
If you want to use each() to process the entire hash, you should always prefix it with keys %HASH. Example:
keys %HASH; # keys will reset the hash iterator
while (my ($k, $v) = each %HASH) { # will really process the ENTIRE hash
}
Mark Reeds Example above would also always work, since he calls keys %ENV before performing the while-each-loop. Through his use of keys() the hash iterator is reset, and as such the while-each-loop will process the entire hash.
Upvotes: 0
Reputation: 95252
Calling keys
inside the loop resets the iterator used by each
. Don't do that. This should work:
my @k = keys (%ENV);
while (my ($k, $v) = each (%ENV)){
if($k eq $k[0]){
print "ok";
}
}
Upvotes: 9
Reputation:
The keys
(and also the values
) functions reset the iterator used by the each
function. As the keys do not change you could retrieve them outside of the loop.
Upvotes: 12