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

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

Thanks Your Mother and citromatik, that was inspirational really...my actual question is actually like this:::: i want to print an array backward one element at a time using pop() and the the last index holder "$#array", but $#array just does not work properly when placed in a while(){} condition or a for(){}, suppose:
@array=(1,2,3,4,5,6,7,8,9); while($index < $#array+1){ $last=pop(@array); print "$last\n"; $index++; }
this code only prints (9 .. 5) but this code works just fine
@array=(1,2,3,4,5,6,7,8,9); $end=($#array+1); while($index < $end){ $last=pop(@array); print "$last\n"; $index++; }

Replies are listed 'Best First'.
Re: $#array issue
by Your Mother (Archbishop) on Jun 14, 2009 at 22:59 UTC

    You've got your $end commented out (update: your example runs fine when it's not). :) Use strict and warnings. It'll save you much trouble. Also, tracking an index in this situation is a bit artificial. You're already destroying the array so just use that as your end point (the existence of elements in the array).

    use warnings; use strict; my @array= ( 1 .. 9 ); while ( @array ) { my $last = pop @array; print "$last\n"; } # ...or... my @array= ( 1 .. 9 ); print "$_\n" while $_ = pop @array;
Re: $#array issue
by Your Mother (Archbishop) on Jun 14, 2009 at 23:21 UTC

    Give this a try and you'll see the problem. It's related to the "destroying the array" solution earlier.

    my @array= ( 1 .. 9 ); my $index; while( $index < $#array+1 ) { my $last = pop(@array); print "$index < ", $#array+1, "\n"; $index++; }

    You shouldn't really update your original post; it gets confusing then because the thread of replies start to look bizarre or wrong. Better to reply with a new post.

Re: $#array issue
by citromatik (Curate) on Jun 14, 2009 at 23:01 UTC

    If you comment the second line, $end will be undefined in the loop condition. Please, use strict and use warnings in your code if you want to learn Perl the easy way. This code works as expected:

    use strict; use warnings; my @array=(1,2,3,4,5,6,7,8,9); my $end=($#array+1); my $index = 0; while($index < $end){ my $last=pop(@array); print "$last\n"; $index++; }

    BTW, here are another ways to address the same problem:

    my @array = (1..9); print +(pop @array),"\n" while (@array);

    or even

    my @array = (1..9); print "array[$_]\n" for (reverse (0..$#array));

    citromatik

      perl -le 'print and sleep 1 for 1 .. 3, "Jinx, you owe me a Coke."'
Re: $#array issue
by shmem (Chancellor) on Jun 14, 2009 at 23:59 UTC
    while($index < $#array+1){ $last=pop(@array);

    You modify your @array while iterating over it. Don't.

    Do you know what $#array holds after the first iteration?

Re: $#array issue
by jwkrahn (Abbot) on Jun 14, 2009 at 23:32 UTC
    i want to print an array backward one element at a time

    Another way to do it:

    $ perl -le' my @array = 1 .. 9; for my $index ( 1 .. @array ) { print $array[ -$index ]; } # "pop" the elements off splice @array; ' 9 8 7 6 5 4 3 2 1
Re: $#array issue
by JavaFan (Canon) on Jun 14, 2009 at 23:28 UTC
    $#array is the index of the last element. pop shortens the array. In your condition, you have
    $index < $#array + 1
    while in your body, you both increase $index and decrease $#array. So, after printing 5, $index is no longer less than $#array + 1, and hence the loop terminates.

    Why not

    my @array = (1 .. 9); while (@array) { my $last = pop @array; print "$last\n"; }
    Or some alternatives:
    my @array = reverse (1 .. 9); print "$_\n" for @array; my @array = (1 .. 9); my $index = $#array; while ($index >= 0) { print $array[$index], "\n"; $index--; } my @array = (1 .. 9); for (my $index = $#array; $index >=0; $index--) { print $array[$index], "\n"; }
Re: $#array issue
by QM (Parson) on Jun 15, 2009 at 18:44 UTC
    Lot's of good answers. Maybe this is short and sweet?
    @array = (1..9); while (@array){ print +(pop @array), "\n"; }

    If you really need that element for something along with the print, you can do this:

    @array = (1..9); while (@array){ my $last = pop @array; do_something($last); print "$last\n"; }

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

Re: $#array issue
by shmem (Chancellor) on Jun 15, 2009 at 00:05 UTC
    while($index < $#array+1){ $last=pop(@array);

    You modify your @array while iterating over it. Don't.

      Thanks to everybody who has replied to my post on $#array... I never noticed that I was modifying both $index and $#array issue, everybody else seemed to have noticed the issue...and "your mother" thumps up, I will use that trick in debugging... the issue is that I am learning Perl entirely on my own and so sometimes I missout on such things...