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

Hey perl lovers,

I'm trying to learn perl, I have this code:

%some_hash = ("foo", 35, "bar", 12.4, 2.5, "hello", "wilma", 1.72e30, +"betty", "bye\n"); while ( ($key, $value) = each %some_hash ) { print("number". $s++); print "$key => $value\n"; }
This enters an infinite loop and the output is
number0betty => bye number1betty => bye number2betty => bye number3betty => bye number4betty => bye . . .

Am I missing something here? I was expecting the loop to print out every element in the hash, but it doesn't. Any help appreciated.

I just discovered that it happens in my debugger only. I have an ubuntu installation with perl, eclipse and epic plugings. I have the padwalker installed. When I step in to the loop, it results in infinite loop. When directly run, it works fine as expected.

I have come up with so many problems, i'll almost give up on perl. This is really frustrating. I spent a week setting up the box and getting perl running with the debugger, now this...

Replies are listed 'Best First'.
Re: Infinite loop with each
by Old_Gray_Bear (Bishop) on Jun 05, 2008 at 05:04 UTC
    You Said:

    When I step in to the loop, it results in infinite loop. When directly run, it works fine as expected.

    The crucial point to take away from this is that your debugger is a bit buggy -- it is altering your code and resetting the iterator that each() uses to keep its sanity.

    Eclipse is a good IDE framework for languages that need an IDE framework. Perl really doesn't need it, though. There is a very serviceable debugger already at your beck-and-call in the '-d' switch (perl -d my-new-perl-program). There is no real need to go and buy a Ferrari when you already have a VW-Beetle in the garage.

    I played with Eclipse and various of its plug-ins and friends a few years back when I was learning to loathe Java. Eclipse is a nice tool, it just isn't really needed with Perl. I have been using vim in one window and perl -d on the command-line in another window rather successfully for the past mumbledy years ....

    ----
    I Go Back to Sleep, Now.

    OGB

Re: Infinite loop with each
by ikegami (Patriarch) on Jun 05, 2008 at 04:18 UTC

    each is inherently fragile since it uses an iterator you don't control. That's why I prefer using keys.

    for my $key ( keys %some_hash ) { my $val = $some_hash{$key}; ... }

    For example, each doesn't work with last or die.

    >perl -le"%h=qw(a ! b @); for(1..2){ for$k(keys%h){ print ++$i,$k; las +t } }" 1a 2a >perl -le"%h=qw(a ! b @); for(1..2){ while($k=each%h){ print ++$i,$k; +last } }" 1a 2b <-- b???

    Update: Added example.

      I'm going to have to disagree with you categorically.
      • You do control the each iterator. You just don't explicitly create it. It's very simple to reset the iterator, should you choose, with a void keys call. I do not consider this a hack.
      • In many Perls, lazy lists aren't fully implemented in for(keys%h). This means that large lists can grow your RAM unnecessarily.
      • When using a tied datastructure, such as from DBM::Deep, each() is strongly preferred due to the way tie implements hash iteration. TIEHASH provides FIRSTKEY and NEXTKEY($current_key). each() calls the methods each iteration and is generally nice. keys() has to call FIRSTKEY, then NEXTKEY($current_key) successively until it returns undef. This can be extremely costly.

      My criteria for good software:
      1. Does it work?
      2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re: Infinite loop with each
by ysth (Canon) on Jun 05, 2008 at 03:26 UTC
    If the debugger is doing something that reads %some_hash, that will affect where the each() iterator is. If it reads all of %some_hash, or does scalar context keys or values on it, the next each() will return the first key/value every time.

      I am pretty sure the debugger is reading the contents of %some_hash. Because EPIC debugger uses padwalker module to take a look into lexical variables. It displays the variables in a window and at every step of the debugging, that window is refreshed.

      What is the best way to debug perl? Even such simple debugging is creating problems of its own. I just need to see variables at every step, and I need to know what the program does in each step. In that code for ex, the stepping is not working properly either, I cannot see the statement inside the while condition being executed.

      I'm just looking for a GUI based IDE that is easy to use so I can focus on my code rather than peculiarities of debugger.

      Guys: this seems to be a known problem in Perl 5 debugger.

      I have encountered this problem both in Padre and in EPIC on Eclipse. So it's not a Padre or Eclipse/EPIC problem. It's a Perl 5 debugger problem.

      See here (already in 2006) and here.

      This should be in PerlFaq, in my opinion. Has anyone found a solution?

Re: Infinite loop with each
by GrandFather (Saint) on Jun 05, 2008 at 04:11 UTC

    We strongly recommend that you use strictures (use strict; use warnings;) for all your Perl scripts.

    The fat comma => makes it a lot easier to check that initialization lists for hashes are correct. Consider:

    my %some_hash = ( foo => 35, bar => 12.4, 2.5 => "hello", wilma => 1.72e30, betty => "bye\n" );

    Perl is environmentally friendly - it saves trees
Re: Infinite loop with each
by Gangabass (Vicar) on Jun 05, 2008 at 03:42 UTC

    This code works fine for me:

    my %some_hash = ("foo", 35, "bar", 12.4, 2.5, "hello", "wilma", 1.72e +30, "betty", "bye\n"); my $s = 0; while ( my ($key, $value) = each %some_hash ) { print("number". $s++); print "$key => $value\n"; }

    But as you can see i add quote to the left of wilma"...

      Thank you for your reply.

      Are you using Eclipse with EPIC and using the debugger to step through the code ?

      The code works for me too, but my problem is with the debugger.

      P.S. the missing quote before wilma was a typo. Corrected it in the original post.