问题
1.Why does while (<$filehandle>)
iterate through a file seemlessly, but it doesn't iterate through lists or arrays without manipulating the array itself (like using while ($_ = shift @array){print $_}
? How does this happen?
2.How is it that while ($var = @array){print $var}
manages to iterate through the whole array? Shouldn't $var
just get the number of indices in @array
and return that value (so creating an infinite loop)?
From my understanding while()
reads the conditionality of a statement and loops as long as it finds it true. What I find confusing though is its behaviour around filehandles, lists and the such.
Please help me understand more about while()
as I find this operator very confusing sometimes.
回答1:
Let's start by looking at while(<$filehandle>)
. This is actually Perl shorthand for this:
while (defined($_ = <$filehandle>)) {
print $_;
}
So each time through the loop, you're reading the next line from the file, and if it is not defined, you'll quit out of the loop. If it is defined, you'll continue. As you expect, while
will loop as long as the condition evaluates to true.
You'll be able to see that by running perl -MO=Deparse program.pl
. You can also check out the documentation under Loop Control. The diamond operator is the same thing as the subroutine readline (it reads the next line from the file).
In the case for while ($_ = shift @array){print $_}
, you will be modifying the array when the condition for the while
loop is checked. The subroutine shift removes the first element of the array and returns it. So $_
will be set correctly, but your array will start losing elements.
In the next case, while ($var = @array){print $var}
, $var
will be equal to the number of elements in the array. It's because you're using @array
in a scalar context. This will mostly likely evaluate to true because from perlsyn
The number 0, the strings '0' and "" , the empty list () , and undef are all false in a boolean context. All other values are true.
Take this one-liner for example:
perl -le 'my @array = qw(a b c d e); my $var = @array; print $var'
It will print the number 5
, because there are 5 elements in the array. The while
loop will not execute if you have 0 elements in your array, and it will be stuck in an infinite loop if there are 1 or more elements in it.
Example:
### This code will print 5 forever ###
my @array = qw(hi this is a test);
my $var;
while ( $var = @array ) {
print "$var\n";
}
For your question 2, it sounds like you are getting different results but this does get stuck in a loop for me.
回答2:
If you are going to use Perl, you will have to get comfortable with special cases.
In the first case, what's special is the diamond operator (<>).
Be careful with 2 as it will break on false values, IIRC.
来源:https://stackoverflow.com/questions/21950535/perl-please-explain-to-me-the-following-behaviours-of-while