http://qs1969.pair.com?node_id=468034

SilverB1rd has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I'm having trouble locating the cuase of an endless loop while I trasvers a complex data structure. The endless loop happens in the second foreach statment but after looking over the camel I have not found any hints as to what is wrong. The wisdom of my fellow monks is much needed.
use strict; my $name = 'test'; my %test; push @{$test{"$name"}}, { name => 'me',age => 'here' }; push @{$test{"$name"}}, { name => 'meAgain',age => 'Nowhere' }; push @{$test{"two"}}, { name => 'you',age => 'there' }; push @{$test{"two"}}, { name => 'AndYou',age => 'AndThere' }; my ($s,$u,$n); foreach $s (keys %test) { foreach $u ( @{$test{$s}} ) { foreach $n (keys %{$test{$s}[$u]}) { print "$s $u $n: $test{$s}[$u]{$n} - \n"; } } }

------
PT - Perl Tanks %100 Perl programming game
The Price of Freedom is Eternal Vigilance

Replies are listed 'Best First'.
Re: Cause of an endless loop?
by tlm (Prior) on Jun 18, 2005 at 21:46 UTC

    The problem was that in your original code you were treating $u ambiguously: both as a hashref and as an array index. The code below fixes it:

    Update: My original solution fixed the infinite looping, but produced an output different from what I think the OP intended; the version above fixes that.

    BTW, the price of eternal vigilance is using warnings. With use warnings, this is what your original code produces:

    Use of reference "HASH(0x814ccf0)" as array index at 468034.pl line 20 +. Out of memory!

    the lowliest monk

Re: Cause of an endless loop?
by davidrw (Prior) on Jun 18, 2005 at 22:15 UTC
    a second approach to the one above that refactors it a little bit -- hopefully will make it a little clearer on how the structure is traversed.
    while( my ($s, $u_arr) = each %test ){ foreach my $u_idx ( 0..$#$u_arr ){ my $u = $u_arr->[$u_idx]; while( my ($n, $value) = each %$u ){ print "$s $u_idx $n: $value - \n"; } } }
    And if you don't care about the index, it can be:
    while( my ($s, $u_arr) = each %test ){ foreach my $u ( @$u_arr ){ while( my ($n, $value) = each %$u ){ print "$s $n: $value - \n"; } } }
    Also, the naming of the temp variables (e.g. $user instead of $u, etc) in this case can make a huge difference in trying to figure out where you are in the complex data structure (or when you revist this code at a later date).