http://www.perlmonks.org?node_id=646301

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

I'm having trouble printing an array using a while loop. We are required to use the while loop to print it, not the for each like we would normally do. I tried it a few different ways, but I keep getting a endless loop. The array is @array = eq(ball, bat, helmet) I'm new to PERL and could use your help. Thanks!

Replies are listed 'Best First'.
Re: Printing an array using while loop
by Joost (Canon) on Oct 21, 2007 at 20:27 UTC
      shouldnt this be really easy?
      my $counter = 0; while($counter <= $#array) { #do your thing $counter++; }
        shouldnt this be really easy?

        Uncountable numbers of fencepost errors in C programs argue otherwise.

      # The solution to your problem is to put handles <> on your array: while(my $item = <@array>) { print("$item\n"); }
        put handles <> on your array: while(my $item = <@array>) { print("$item\n"); }

        Although this works in this particular case, I wouldn't recommend it: The <> actually doesn't do anything with "handles" (like <$filehandle>, which is readline), instead it's glob in disguise, and glob has several caveats. I would suggest a regular foreach, or perhaps each (Perl >= 5.12, which was not available in 2007, at the time of this thread).

        $ perl -MO=Deparse -e 'while(my $item = <@array>) { print "$item\n" }' while (defined(my $item = glob(join $", @array))) { do { use File::Glob (); print "$item\n" }; }
Re: Printing an array using while loop
by moritz (Cardinal) on Oct 21, 2007 at 20:25 UTC
    my $item; while (defined($item = shift @array)){ print $item, "\n"; }

    This destroys @array, though.

    BTW there is no PERL, just perl (the interpreter) and Perl (the language)

    Update: made 0-safe

      Update: made 0-safe

      But still not undef-safe. ;-)

      print shift @array while @array;

      ... which is about the silliest code I've ever written. Sheesh, what's with these arbitrary limitations? :)

      print "Just another Perl ${\(trickster and hacker)},"
      The Sidhekin proves Sidhe did it!

        Right, the correct solution checks @array, not the returned item.

      You've already been shown how to make your code work with all values including undef.

      while (@array) { my $item = shift(@array); print "$item\n"; }

      If you wanted safe code that didn't refer to the array twice, you could use splice in a list assignment.

      while (my ($item) = splice(@array, 0, 1)) { print "$item\n"; }

      The parens on the LHS of the assignment are crucial to force a list context. The result of a list assignment in list context is the number of list elements assigned (no matter if the element(s) are true or false).

      BTW there is no PERL, just perl (the interpreter) and Perl (the language)
      Of course there is. It's usually used as part of a course name. But the course ends up teaching something really different :-)

      Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

      >> BTW there is no PERL, just perl (the interpreter) and Perl (the language)

      AIUI, the reverse is true; Perl is the interpreter and perl is the language

      /pedant

        No, moritz was correct according to the FAQ.

Re: Printing an array using while loop
by rminner (Chaplain) on Oct 21, 2007 at 22:09 UTC
    A for loop can always be written like a while loop
    my @array = qw{ball bat helmet}; my $i=0; while ($i<=$#array) { print $array[$i],"\n"; $i++; }
Re: Printing an array using while loop
by perlfan (Vicar) on Oct 21, 2007 at 22:52 UTC
    or:
    my @array1 = qw/ball bat helmet/; while (@array1) { my $item = pop @array1; print $item; push(@array2,$item); }
    That is if you care about keeping the original contents - otherwise:
    my @array1 = qw/ball bat helmet/; while (@array1) { print pop @array1; }

      If order is important, pop is wrong in both examples:

      c:\@Work\Perl\monks>perl -wMstrict -le "my @array1 = qw/ball bat helmet/; print qq{\@array1 before: (@array1)}; ;; my @array2; while (@array1) { my $item = pop @array1; print $item; push(@array2,$item); } print qq{\@array2 after: (@array2)}; " @array1 before: (ball bat helmet) helmet bat ball @array2 after: (helmet bat ball)
      shift does the trick:
      c:\@Work\Perl\monks>perl -wMstrict -e "use Data::Dump qw(dd); ;; my @array1 = (qw/ball bat helmet/, 0, undef); dd '@array1 before:', \@array1; ;; my @array2; while (@array1) { my $item = shift @array1; dd $item; push(@array2,$item); } dd '@array2 after:', \@array2; " ("\@array1 before:", ["ball", "bat", "helmet", 0, undef]) "ball" "bat" "helmet" 0 undef ("\@array2 after:", ["ball", "bat", "helmet", 0, undef])


      Give a man a fish:  <%-{-{-{-<

Re: Printing an array using while loop
by Anonymous Monk on Oct 22, 2007 at 05:52 UTC
    while (1) { print "@array", "\n"; last; }
      In addition to using a "last" in a while loop - which is not good practice, this solution goes against the spirit of the OP's question.
        Well it made me laugh, especially as the "spirit of the OP's question" is obviously homework. :)