http://www.perlmonks.org?node_id=1006749


in reply to How does while works with filehandles?

Usually, while( EXPRESSION ) stops looping when the expression becomes false, but Perl has an exception to that rule: if the expression is just reading a line from a file (and perhaps assigning it to a variable), then it only stops looping when the expression is undefined (undefined is false of course, but there are certain values which are false but defined).

This works in conjunction with the fact that reading a line from a file that has reached its end will return undef.

Observe the difference:

$ echo -n "0" | perl -E'while(<>) { say "GOT" }' GOT $ echo -n "0" | perl -E'while(<> and 1) { say "GOT" }' $

The first one prints "GOT" even though it read a false value from STDIN. This is because the special "reading from a filehandle" version of while gets used. The second doesn't print "GOT". This is because the more complex expression forces while to use its standard behaviour.

There is another interesting aspect of the reading-from-filehandle version of while: if you don't assign the line to a variable, it gets assigned to $_. This doesn't happen when you read from a filehandle normally - only within while. Observe:

$ echo "Hello" | perl -E'while(<>){ print $_ }' Hello $ echo "Hello" | perl -E'<>; print $_' $

So anyway, while (<$fh>) works out as being equivalent to:

while (defined($_ = <$fh>))

... which (by design, not just by luck) happens to be the kind of loop most people usually want when they're reading from a file.

I suppose the other thing that is worth mentioning is the special variable $/ which is used by readline (an thus by <$fh>) to determine the current line ending. By default it's "\n" but you can set it to anything else you like, including undef.

perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'