in reply to Nested while each over a hash -> infinite loop

From the documentation for each:

After each has returned all entries from the hash or array, the next call to each returns the empty list in list context and undef in scalar context. The next call following that one restarts iteration.

The outer while loop grabs the only element in %test. The inner while loop gets an empty list, and consequently never executes. So the outer while loop tests each again. This time it has reset, so it again returns the first (and only) element from %test.

Nothing wrong with Perl. Your script is flawed.

Also, if you were using use strict; at the top of your script you would have discovered that print $name1 is not working out so well, since there is no $name1. The outer loop creates $name, not $name1. Furthermore, your code won't even compile as your outer while loop's parens don't nest properly.

You may want something more like this:

use strict; use warnings; my %test = ('a' => {'b' => 'b'}); while ( my ( $name, $value ) = each %test ) { print $name; while ( my ( $name2, $value2 ) = each %{ $value } ) { print $name2; } }

Dave

Replies are listed 'Best First'.
Re^2: Nested while each over a hash -> infinite loop
by Eythil (Acolyte) on Jun 10, 2011 at 08:09 UTC
    Ah, now I get it. Thanks.

    The $name1 thing was a typo. I have to use different computers for scripting and for browsing the web.

    Cloning before the first while loop seems to work. I think I will go with that.

      My original post has been updated with some code to show how to do what you probably intended to do. Have a look. I think it will get you back on track. You may need to browse over one or more of the following: perlreftut, perllol, and perldsc.


      Dave

        I think I should explain my problem a bit more in detail: I have a hash like
        my $test = ( 'a' => { 'identifiers' => { 'mrt1' => 1, 'mrt2' => 1, 'mrt3' => 1, }, }, 'b' => { 'identifiers' => { 'mrt2' => 1, 'mrt3' => 1, 'mrt6' => 1, }, }, 'c' => { 'identifiers' => { 'mrt1' => 1, 'mrt2' => 1, 'mrt3' => 1, }, }, 'd' => { 'identifiers' => { 'mrt2' => 1, 'mrt3' => 1, 'mrt6' => 1, }, }, 'sum_ab' => { 'values' => { 'a' => 1, 'b' => 1, }, }, 'sum_cd' => { 'values' => { 'c' => 1, 'd' => 1, }, }, 'sum_abcd' => { 'values' => { 'sum_ab' => 1, 'sum_cd' => 1, }, }, );
        In case of mrt1 I do something, because a is matched. Afterwards I need to do something, because sum_ab has a in its 'values'-hash. Afterwards I have to check if some sum includes 'sum_ab' and so on...

        That is the reason, why I wanted to use the nested iteration over the same hash. Perhaps I could push to some temporary variable and do the second while after the first one.