#
=begin perlmonkcomment
Today i ran into a small problem:
I wrote a small helper function which gets me some data from a hash.
I am not accessing the hash directly, as i do not know the exact name of the key
so i am forced to do some pattern matching on all hashkeys (well, at least until i get a match).
Strangely it sometimes found the element in the hash and sometimes it didn't, even though the info was always present.
It took me some time to find out, that the iterator for that hash wasn't reseted properly.
Quoting the Perl FAQ:
How do I reset an each() operation part-way through?
> Using keys %hash in scalar context returns the number of keys in the hash and resets the iterator associated with the hash. You may need to do this if you use last to exit a loop early so that when you re-enter it, the hash iterator has been reset.
What confused me was, that i have to do this resetting every time i enter my subroutine. (This Problem also ocurrs if i exit the loop using a return statement instead of last).
The thing is i tend to use those while ( my ($x ,$y) = each %hash) constructs quite frequently to iterate over all elements of a hash. Unfortunately this behaviour would force me to manually reset the hash iterator through the use of &keys every time i use this construct, in order to be really sure that i am truly iterating over all elements.
Now my question is: is it always necessary to reset the iterator before using each, or is there a trick where i won't have to call keys everytime before using it (as i said, i use it to iterate over all elements).
Demo Programm for the problem:
(not my real function, but a simplified example)
=cut
$::WORKAROUND = 0;
sub find_in {
my ($data_ref, $string) = @_;
my $result = 'no result';
# reset the iterator for %$data_ref:
keys %$data_ref if ($::WORKAROUND);
while ( my ($name , $value) = each %$data_ref) {
if (lc($name) eq lc($string)) {
$result = $value;
last;
}
}
return $result;
}
sub look_for_data {
my %hash = ( A => 'xxx' , B => 'xxx' , C => 'xxx' , D => 'xxx');
print "D: " . find_in(\%hash , 'D') . "\n";
print "A: " . find_in(\%hash , 'A') . "\n";
print "B: " . find_in(\%hash , 'B') . "\n";
print "B: " . find_in(\%hash , 'B') . "\n";
}
print "# NO workaround:\n";
look_for_data();
print "# WITH workaround:\n";
$::WORKAROUND=1;
look_for_data();
=begin perlmonk_comment
Output of the Programm:
# NO workaround:
D: xxx
A: no result
B: xxx
B: no result
# WITH workaround:
D: xxx
A: xxx
B: xxx
B: xxx
=cut
#
UPDATE: As pointed out by jhedden my problem is already covered in the thread
The Anomalous each()