in reply to The anomalous each()--Part II.

Wow! Your example was educative, I couldn't see the bug.

Replies are listed 'Best First'.
Re^2: The anomalous each()--Part II.
by BrowserUk (Patriarch) on Nov 19, 2005 at 20:21 UTC
    Am I correct that this is what you meant by saying each in scalar context?

    What I meant by scalar context is that it is more usual to see each used as

    while( my( $key, $value ) = each %hash ) { ...

    Which puts the call to each into a list context.

    Although using each in a scalar context is a perfectly legitimate thing to do (from perlfunc):

    When called in list context, returns a 2-element list consisting of the key and value for the next element of a hash, so that you can iterate over it. When called in scalar context, returns only the key for the next element in the hash.

    You rarely see this use, and when I discovered this anomoly, that was where I thought the problem lay.

    Also, using the hash in an rvalue resets the iterator only if it's in list context. If you change %h to scalar(%h), the loop does end after iterating through all elements.

    Indeed. When I came across the problem, the code was something like this.

    while( my $key = each %hash ) { ... my %reversed = reverse %h; ... }

    The first thing I did to try and work out what was going on was to add the line

    print "$key: ", %hash;

    That showed me that each was producing the same (first) key over and over. Even when I had commented out everything in the loop (except the debug print line), it still looped forever. Hence the problem *had* to be the loop condition. Didn't it?

    It took a long time to work out that the print line itself was duplicating the situation that was originally caused by using %hash as an rvalue in the line above.

    All in all a rather elusive problem. I guess that the behaviour is covered by the line in the perlfunc that reads:

    There is a single iterator for each hash, shared by all each, keys, and values function calls in the program;

    but I'd have to say that I think that it should be clearer that this includes uses of those functions that are invoked by Perl itself, and only indirectly as a result of what the programmer is doing.

    I can't help but think that Perl could localise the hash before using it internally?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.