while (...each(%h)...) {
...
last if ...;
...
}
The solution is
keys(%h); # Reset iterator.
while (...each(%h)...) {
...
last if ...;
...
}
Note that keys does not actually compute the list of keys in void context. | [reply] [d/l] [select] |
Indeed, you can insert a keys call prior to using 'each' in every instance, presuming you're not already in the middle of an 'each' on that hash already, and thereby reset the iterator mid-stream:
my %h = qw( one 1 two 2 three 3 four 4 );
while (my($k, $v) = each %h) {
say "$k=$v";
frobnicate(\%h);
}
sub frobnicate { keys %{ $_[0] } }
Admittedly, this example is a bit contrived, but it's generally unexpected that your loop becomes infinite just from simple calls that don't appear to modify the hash. The workaround is obvious, if restricting: don't pass the hashref to any functions (including functions with prototypes that auto-enreference it). It's even worse if the hash is global; you essentially can't call any functions, for fear that, somewhere in the call chain, something will call 'keys' on the hash.
In my opinion, it's too many caveats to make 'each' very useful. | [reply] [d/l] |
I don't use mod_perl, but I would have assumed that the scenario you describe would only occur if the hash was a global?
And isn't using globals in persistent environment one of the (many) no-nos? Or at least, something you are warned about that you must take extra care with.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] |