title: What's the most defensive way to loop through lines in a file with Perl?
body: <p>I usually loop through lines in a file using the following code:</p>
  
  <pre><code>open my $fh, '&lt;', $file or die "Could not open file $file for reading: $!\n";
  while ( my $line = &lt;$fh&gt; ) {
    ...
  }
  </code></pre>
  
  <p>However, <a href="https://stackoverflow.com/questions/3773017/why-do-du-and-perls-s-give-different-values-for-the-file-size/3773124#3773124">in answering another question</a>, <a href="https://stackoverflow.com/users/124486/evan-carroll">Evan Carroll</a> edited my answer, changing my <code>while</code> statement to:</p>
  
  <pre><code>while ( defined( my $line = &lt;$fh&gt; ) ) {
    ...
  }
  </code></pre>
  
  <p>His rationale was that if you have a line that's <code>0</code> (it'd have to be the last line, else it would have a carriage return) then your <code>while</code> would exit prematurely if you used my statement (<code>$line</code> would be set to <code>"0"</code>, and the return value from the assignment would thus also be <code>"0"</code> which gets evaluated to false). If you check for defined-ness, then you don't run into this problem. It makes perfect sense.</p>
  
  <p>So I tried it. I created a textfile whose last line is <code>0</code> with no carriage return on it. I ran it through my loop and the loop did not exit prematurely.</p>
  
  <p>I then thought, "Aha, maybe the value isn't actually <code>0</code>, maybe there's something else there that's screwing things up!" So I used <code>Dump()</code> from <code>Devel::Peek</code> and this is what it gave me:</p>
  
  <pre><code>SV = PV(0x635088) at 0x92f0e8
    REFCNT = 1
    FLAGS = (PADMY,POK,pPOK)
    PV = 0X962600 "0"\0
    CUR = 1
    LEN = 80
  </code></pre>
  
  <p>That seems to tell me that the value is actually the string <code>"0"</code>, as I get a similar result if I call <code>Dump()</code> on a scalar I've explicitly set to <code>"0"</code> (the only difference is in the LEN field -- from the file LEN is 80, whereas from the scalar LEN is 8).</p>
  
  <p>So what's the deal? Why doesn't my <code>while()</code> loop exit prematurely if I pass it a line that's only <code>"0"</code> with no carriage return? Is Evan's loop actually more defensive, or does Perl do something crazy internally that means you don't need to worry about these things and <code>while()</code> actually only does exit when you hit <code>eof</code>?</p>