<?xml version="1.0" encoding="windows-1252"?>
<node id="1006749" title="Re: How does while works with filehandles?" created="2012-12-02 14:22:32" updated="2012-12-02 14:22:32">
<type id="11">
note</type>
<author id="757127">
tobyink</author>
<data>
<field name="doctext">
&lt;p&gt;Usually, &lt;c&gt;while( EXPRESSION )&lt;/c&gt; 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 &lt;em&gt;undefined&lt;/em&gt; (undefined is false of course, but there are certain values which are false but defined).&lt;/p&gt;

&lt;p&gt;This works in conjunction with the fact that reading a line from a file that has reached its end will return undef.&lt;/p&gt;

&lt;p&gt;Observe the difference:&lt;/p&gt;

&lt;c&gt;
$ echo -n "0" | perl -E'while(&lt;&gt;) { say "GOT" }'
GOT
$ echo -n "0" | perl -E'while(&lt;&gt; and 1) { say "GOT" }'
$ 
&lt;/c&gt;

&lt;p&gt;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 &lt;c&gt;while&lt;/c&gt; gets used. The second doesn't print "GOT". This is because the more complex expression forces &lt;c&gt;while&lt;/c&gt; to use its standard behaviour.&lt;/p&gt;

&lt;p&gt;There is another interesting aspect of the reading-from-filehandle version of &lt;c&gt;while&lt;/c&gt;: if you don't assign the line to a variable, it gets assigned to &lt;c&gt;$_&lt;/c&gt;. This doesn't happen when you read from a filehandle normally - only within &lt;c&gt;while&lt;/c&gt;. Observe:&lt;/p&gt;

&lt;c&gt;
$ echo "Hello" | perl -E'while(&lt;&gt;){ print $_ }'
Hello
$ echo "Hello" | perl -E'&lt;&gt;; print $_'
$
&lt;/c&gt;

&lt;p&gt;So anyway, &lt;c&gt;while (&lt;$fh&gt;)&lt;/c&gt; works out as being equivalent to:&lt;/p&gt;

&lt;c&gt;
while (defined($_ = &lt;$fh&gt;))
&lt;/c&gt;

&lt;p&gt;... 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.&lt;/p&gt;

&lt;p&gt;I suppose the other thing that is worth mentioning is the special variable &lt;c&gt;$/&lt;/c&gt; which is used by &lt;c&gt;readline&lt;/c&gt; (an thus by &lt;c&gt;&lt;$fh&gt;&lt;/c&gt;) to determine the current line ending. By default it's &lt;c&gt;"\n"&lt;/c&gt; but you can set it to anything else you like, including undef.&lt;/p&gt;

&lt;!-- Node text goes above. Div tags should contain sig only --&gt;
&lt;div class="pmsig"&gt;&lt;div class="pmsig-757127"&gt;
&lt;small&gt;&lt;small&gt;
&lt;tt&gt;perl -E'sub Monkey::do{say$_,for@_,do{($monkey=&amp;#x5B;caller(0)]-&gt;&amp;#x5B;3])=~s{::}{ }and$monkey}}"Monkey say"-&gt;Monkey::do'
&lt;/tt&gt;&lt;/small&gt;&lt;/small&gt;
&lt;/div&gt;&lt;/div&gt;</field>
<field name="root_node">
1006738</field>
<field name="parent_node">
1006738</field>
</data>
</node>
