I have a minimal working example of two nested while loops on the same array @g:
#!/usr/bin/env perl
use 5.042;
no source::encoding;
use warnings FATAL => 'all';
use feature 'say';
use autodie ':default';
my @g = qw(Matthew Mark Luke John);
while (my ($i, $gos) = each @g) {
say "$i => $gos";
while (my ($j, $g2) = each @g) {
say "\t$j=>$g2";
}
}
This particular loop gets stuck on the first iteration $i, and never moves on to the 2nd.
The infinity is easily fixed by foreach my $gos (@gos) { instead of the first while.
Is this a bug or an intended feature?
Shouldn't foreach my $gos (@g) in the first line be the exact equivalent of while (my ($i, $gos) = each @g) {?
Since you are using v5.42, you should use foreach and indexed which is designed to do just this:
use 5.042;
$|=1;
my @g = qw(Matthew Mark Luke John);
foreach my($i, $gos) ( indexed @g ) {
say "$i => $gos";
foreach my($j, $g2) ( indexed @g ) {
say "\t$j=>$g2";
}
}
The problem is that both invocations of each use the same list iterator. From the perldoc:
Each hash or array has its own internal iterator, accessed by
each,keys, andvalues. The iterator is implicitly reset wheneachhas reached the end [...]
After returning all elements, the iterator returns an empty list in the inner loop, upon which it restarts from the beginning. This is why your outer loop never progresses beyond the first element: all remaining elements are consumed by the inner loop on every iteration.
The repeated output you're seeing clearly demonstrates the shared iterator behavior:
0=>Matthew # Consumed by outer loop
1=>Mark # Consumed by inner loop
2=>Luke # Consumed by inner loop
3=>John # Consumed by inner loop
() # Iterator is exhausted and reset. Loop exits
0=>Matthew # A fresh iterator
1=>Mark
2=>Luke
3=>John
() # Iterator is exhausted and reset. Loop exits
# ... and so on
You should use foreach instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With