Todd Iglehart
Todd Iglehart

Reputation: 17

while inside foreach kills original array

For some reason my original array gets wiped out with this code. I can't figure out why? @my_array is empty after running this, I took out all the work in the while loop to see if that was the cause but its not.

foreach (@my_array)
{
    open MY_FH, "<", $_;
    while (<MY_FH>)
        {
        }
    close MY_FH;
}

Upvotes: 0

Views: 204

Answers (2)

Borodin
Borodin

Reputation: 126772

As cjm has explained, the elements of the array are overwritten by the while loop because it reads from the file into $_, which the foreach aliases to each array element in turn

The simplest solution is to localise $_ for the duration of the while loop. That creates a temporary copy of $_ that can be used without affecting @my_array. Like this

for ( @my_array ) {

    open my $fh, '<', $_;

    local $_;    # To protect @my_array

    while ( <$fh> ) {
        ...
    }
    close $fh;
}

Upvotes: 0

cjm
cjm

Reputation: 62109

It's not empty, it's just full of undef.

while (<MY_FH>) is syntactic sugar for while (defined($_ = <MY_FH>)). Since the variable in a foreach loop is an alias to the original value, the filename in $_ gets overwritten with each line of the file. The while loop keeps going until <MY_FH> returns undef to indicate EOF. That undef is the last value stored in $_.

The solution is to use a different variable in at least one of the loops. Changing the foreach loop will probably be less work:

foreach my $fn (@my_array)
{
    open MY_FH, "<", $fn;
    while (<MY_FH>)
        {
        }
    close MY_FH;
}

If you checked the size of @my_array after the loop with scalar @my_array, you'd find that it hasn't changed. But an array of undef looks just like an empty array when you're accessing individual elements, which is probably why you think it's empty.

Upvotes: 9

Related Questions