in reply to Array Processing

To elaborate further on what davido and grandfather have said -- you can make it nicely terse using the syntax "while (my $a = shift @a)", as in:
#!/usr/bin/perl -w # Strict use strict; use warnings; # Main program my @a = (1..5); while (my $a = shift @a) { print "Deleted value: $a\n"; }
Now that you are checking for the changing condition (the individually shifted-off element), you will get what you expect.  If you're not going to use any of the values from the array, then as EvanCarroll pointed out, the easier/quicker way to delete all of @a would be:
@a = ( );

Replies are listed 'Best First'.
Re^2: Array Processing
by blokhead (Monsignor) on Oct 08, 2005 at 15:16 UTC
    while (my $a = shift @a) {
    This won't work if the array contains anything that is false in boolean context, like 0, '', or undef. You really need to explicitly check the array's length somehow.

    If you're really intent on squeezing the assignment into the while loop, try:

    while ( (my $a, @a) = @a ) {
    This works because when evaluated in scalar context, the list assignment ( (list) = something ) returns the number of items in the right-hand side list. This little obscurity of syntax is probably one of the toughest to come to grips with, but it can be quite elegant at times.

    In this case, I wouldn't actually use it since it reassigns most of @a to itself every time and is very inefficient in that respect.

    blokhead

      Or use the comma operator: while (@a and my $a = shift @a, 1) { ... }

      (Updated code is in bold)


      Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
      How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
        In reply to blokhead, you're absolutely right about the potential early termination.  And of course, it becomes essential when reading in a file, which could contain blank lines, that instead of:
        while ($line = <$fh>) { # ... }
        you do something like:
        while (defined($line = <$fh>)) { # ... }
        But then, when I looked more carefully at the idiom you suggested, there's a subtle bug in:  while ( (my $a, @a) = @a ) {".  I realized it doesn't, in fact, reasign most of @a to iteslf every time, because you're declaring my @a (along with my $a), so it's a different @a that you're doing the assignment to!  Also, when you run it, you get an infinite loop:
        my @a = qw( 1 2 3 4 5 ); while (my ($a, @a) = shift @a) { printf "Next value = $a\n"; printf "Size of \@a = %d\n", 0 + @a; } # When run ... infinite loop! # (Note that "Size of @a" shows the temporary @a, not the original) Next value = 1 Size of @a = 0 Next value = 2 Size of @a = 0 Next value = 3 Size of @a = 0 Next value = 4 Size of @a = 0 Next value = 5 Size of @a = 0 Next value = Size of @a = 0 Next value = Size of @a = 0 Next value =
        And japhy, you've got an interesting idiom too, but it also doesn't do quite what you want, because the ",1" makes the expression eternally true, so you also get an infinite loop even after @a is exhausted.  So for now, I'll stick with the "while (defined($a = shift @a))" syntax.
Re^2: Array Processing
by Aristotle (Chancellor) on Oct 09, 2005 at 20:06 UTC

    As mentioned by others, that will fail if the array may contain false or undefined values. You can do something similar by keeping the entire assignment in list context and making sure to assign a list:

    while( my ( $a ) = @a ? shift @a : () ) { # ... }

    Note the parens around $a: they make all the difference. They put the my (and thus the entire expression) in list context, and so the boolean value depends on the number of elements assigned. The ternary operator contortion on the right side ensures that when @a is empty, an empty list is assigned, so the loop aborts correctly.

    Try putting empty strings, zeros or undefs in the array: you’ll find it will always do exactly what it’s supposed to.

    However, elegant is not what it is. I’d much rather use while( @a ) and do a separate shift – far fewer subtleties to contend with.

    Makeshifts last the longest.