in reply to The Anomalous each()

No, you've reached an incorrect conclusion. each() works just fine and you don't have to care about how some previous loop exited and whether it reached the end or not. If you call values() or keys() in void context just prior to your new loop, you've reset the iterator to the beginning. void context keys()/values() are extremely cheap operations. Just do it.

keys %data; while ( ... = each %data ) { ... }

Its dumb that a person has to know to use a call to keys() to reset the iterator. I don't like that at all.

Replies are listed 'Best First'.
Re^2: The Anomalous each()
by fletcher_the_dog (Friar) on Nov 18, 2005 at 20:13 UTC
    But you do have to worry if you for some reason call 'each' or 'keys' on a hash in an inner loop of an each loop. There is not really any way around this expect to use 'keys' in your outer loop instead of 'each'.
    # this code creates an endless loop my %hash = ( foo=>"x", Foo=>"y", Bar=>"a", bar=>"c" ); while(my($key,$value)=each %hash){ # dumb example for my $key2 (keys %hash){ if(lc($key) eq lc($key2)){ print "key $key is similiar to $key2\n"; } } }
      Ok, so don't give your hash to functions you don't control if you think that's going to be a problem.
        Better wording would be:
        Caution: Don't use each() for a loop if you have to hand your hash to a function unless you know for sure that the function definitely won't use each()/keys()/values() on it. (It's probably a sure bet that if you hand off a hash to a function it will do just that.)
Re^2: The Anomalous each()
by jdhedden (Deacon) on Nov 18, 2005 at 20:19 UTC
    Gee, so you're saying that using keys() in a void context is a workaround for this bug-like behavior. Your reply would seem to reinforce my conclusion.

    Further, from a code maintainability aspect, the use of keys() would definitely appear to be superfulous, and another maintainer might be inclined to remove it.

    I'll go with using a foreach loop instead:

    foreach my $key (keys(%hash)) { my $val = $hash{$key}; ... }
    when my threashhold of comfort for using each() is not met.

    Remember: There's always one more bug.
      Its not a work-around so much as it is how you've always been supposed to use it. Its not a bug because its designed that way. Or at least isn't *called* a bug. Its pretty dumb behaviour and it makes it easy to make mistakes. The only time I'd ever use each() is on hashes which might have large numbers of keys. It'd be potentially wasteful or fatal to do a loop over keys(%hash) on an especially large hash. When that's possible, then you just have to bite the bullet, use each() and do it safely.
        It's not a work-around so much as it is how you've always been supposed to use it.
        Where is it documented that you need to be proactively cautious when using each() by proceeding it with keys()? Or to make sure you avoid using each() if your hash may be touched by other code inside you loop?

        The perlfunc entry tells you there's one iterator, true, but doesn't give you any insight into the potential pitfalls that may lead to. That was the purpose of my post.