Here's another "What's a quick and real neat way of...." type question

Grant McLean Grantm at
Thu Nov 14 14:40:56 CST 2002

Piers Harding wrote:
> On Thu, Nov 14, 2002 at 11:06:14PM +1300, Enkidu wrote:
> > Is there a neat way of looping through *both arrays* at 
> > the same time?
> how about this:
> while (my ($a, $b) = (shift @a, shift @b)){
>   do the funky thing with $a and $b ....
> }

Interesting suggestion, I wouldn't have expected that to
work, since when @a and @b are empty, the right hand
side of the expression (shift @a, shift @b) evaluates to
(undef, undef) which is a two element list which in boolean
terms is 'true', so the while loop should never exit.

My curiosity was piqued, so I tried it.  The bad news is it 
doesn't work :-(  The good news is I was right ;-/

One approach is to add a line to explicitly break out of 
the loop when the arrays are empty:

  while (my ($a, $b) = (shift @a, shift @b)){
    # do the funky thing with $a and $b ....
    last unless(@a);

At first, I made the mistake of adding this check as the 
first line of the loop.  This meant the loop skipped the 
last element of each array since when the last element was
successfully shifted off, there was nothing left in the 
array.  So, the test needs to go either at the end of the
loop. (I also tried putting it in a continue block but it
didn't work - I guess 'last' won't break out of the main 
block when you call it from another block).

It is possible to combine the test with the assignment in
such a way that the right hand side evaluates to an empty 
list when the arrays are empty:

  while(my($a, $b) = (@a ? (shift @a, shift @b) : ()) ){
    # do the funky thing with $a and $b ....

Anyone have a more elegant solution?


PS: I'm assuming @a and @b are the same length.

Grant McLean        BearingPoint Inc - formerly The Web Limited
+64 4 495 9026           Level 6, 20 Customhouse Quay, Box 1195
gmclean at                Wellington, New Zealand

More information about the Wellington-pm mailing list