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

Fellow monks,

I've run into a problem. I have a list of data in memory, and data in an open file that all need to be wrung through the same process. Typically, i would concatenate the two lists like so:
foreach my $line (@values,<$filehandle>) {
However i've run into a problem. I cannot use a foreach statement for a given problem i am working on - it must be a where statement (reason: i need to be able to get the next value of <$filehandle> from within the loop given certain situations). I tried different variations of the above line, using a where instead, similar to this:
while ($line = (@values,<$filehandle>)) {
All to no avail.

Anyone know a way to replicate this behavior with a where loop?

Many thanks in advance

Replies are listed 'Best First'.
Re: Glob + list = list concatenation
by kvale (Monsignor) on Mar 31, 2004 at 20:35 UTC
    Assuming no lines that evaulate as false,
    my @list = (@values, <$filehandle>); while( my $line = shift @list) { ... my $another_line = shift @list; }
    creates a list situable for iterating through. If you need to pull out various lines of <$filehandle> from the array, use splice:
    my $file_line = splice @list, scalar @values + $line_num,1;
    This will get the file line for you and remove it from the line array all at once.

    Update: elaborated on my answer.

    -Mark

Re: Glob + list = list concatenation
by Roy Johnson (Monsignor) on Mar 31, 2004 at 20:38 UTC
    while (defined(my $line = (@values) ? shift(@values) : <$filehandle>)) + { ...
    Update: the defined is needed.

    The PerlMonk tr/// Advocate
Re: Glob + list = list concatenation
by blokhead (Monsignor) on Mar 31, 2004 at 22:40 UTC
    If you don't want to destroy @values as you go along (as some of the above solutions do), you can make an iterator to return the appropriate "next thing":
    my $iter = do { my $i; sub { $i < @values ? $values[$i++] : <$filehandle> } }; while ( my $line = $iter->() ) { ## do stuff ... }
    The readline on the filehandle is still not performed until needed and @values is kept intact.

    blokhead

Re: Glob + list = list concatenation
by matija (Priest) on Mar 31, 2004 at 20:40 UTC
    I can't think of a way to do what you want (may be other can), but personaly, I would put the whole body of the loop into a subroutine, then do
    while (defined($line=shift @values)) { process($line); } while (defined($line=<$filehandle>)) { process($line); }
    (The reason for keeping the body of the loop in the subroutine is that that way you will be sure you only need to make any changes in one place.