Change Request for perlfaq4

[email protected] ("Roland Minner") Wed, 22 Nov 2006 16:17:37 +0100
Newsgroups perl.perlfaq.workers
Message-ID <[email protected]>
Hello,

I'd like to request a change in perlfaq4. It recommends the usage of each() to iterate over all elements of a hash.
This isn't always true. If this hash was previously used in another subroutine, which used each() to iterate over all elements, and the loop
exited using last() or return(), then the HASH Iterator isn't pointing to the beginning of the hash.
Like that by the next time one uses each() to Iterate over the HASH, one won't be getting all element, but only the ones starting from the position of the hash iterator.
I recommend to change it to be changed to use keys() instead of each(). Or at Least put a note into the answer, that each() doesn't necessarily give you all hash elements.
If you want a demo of the problem, please have a look at:
http://www.perlmonks.org/?node_id=544580


Current> How do I process an entire hash?
Current> 
Current> Use the each() function (see each in perlfunc) if you don't care whether it's sorted:
Current> 
Current>     while ( ($key, $value) = each %hash) {
Current>     print "$key = $value\n";
Current>     }
Current> 
Current> If you want it sorted, you'll have to use foreach() on the result of sorting the keys as shown in an earlier question. 


# Proposed Change:
##############################################################################

How do I process an entire hash?

Using keys() you can iterate over all hash keys: 

foreach my $key (keys %hash) {
    my $value = $hash{$key};
}

If you want to use each() (see each in perlfunc) to iterate over all elements, 
you should make sure that the hash iterator is pointing to the beginning of the 
hash. This can be achieved by calling keys(%hash) before iterating over all 
elemts using each(). 

keys %hash; # <-- keys() resets the hash iterator as a side effect
while ( ($key, $value) = each %hash) { 
    print "$key = $value\n";
}

One Situation where the hash iterator might be pointing to the wrong location is when 
you iterate over the same hash in another part of the programm using each() but exit the loop early using last() or return().
In that case the Hash Iterator is left at the position where the loop was exited.
Next time each() is called it would continue at that point and not at the beginning. 
Like that you would get only a part of the Hash.
So if you are 100% sure your hash iterator is pointing to the beginning of the hash, 
you can skip keys(%hash);. 


Regards

Roland Minner