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


in reply to A refactoring trap

There's another problem with your refactored code:

while (<DATA>) { ... }
is not the same as
while (my $line = <DATA>) { ... }

The first while will stop as soon as <DATA> returns undef, so at the end of the data. The second while however, will stop as soon as it finds an empty line. The correct refactoring should have been:

while (defined (my $line = <DATA>)) { ... }

--
Lyon

Replies are listed 'Best First'.
Re^2: A refactoring trap
by wolv (Pilgrim) on Aug 17, 2005 at 08:23 UTC
    No. This is magic in Perl5:
    wolverian@noesis:~$ perl -MO=Deparse -e'while (my $foo = <DATA>) { }' while (defined(my $foo = <DATA>)) { (); } __DATA__ -e syntax OK
Re^2: A refactoring trap
by Caron (Friar) on Aug 17, 2005 at 07:53 UTC
    The second while however, will stop as soon as it finds an empty line

    Just to test your assertion:

    while (my $line = <DATA>) {print $line}; __DATA__ one two three four

    results in

    one
    
    two
    three
    
    four
    
    

    It seems that empty lines don't break the loop at all.

      Hmmm, you're right. It doesn't break.

      The reason is that blank lines are not truely blank, of course. You're saved by the fact that a blank line still contains the "\n".

      --
      Lyon

        No it still works with chomp:
        while(chomp (my $line = <DATA>)){
        At least with newer perl versions. Tried with perl5.8.6.
Re^2: A refactoring trap
by Anonymous Monk on Aug 17, 2005 at 10:12 UTC
    The problem with
    while (my $line = <HANDLE>) {...}
    is that it stops the loop prematurely if $line is false, but defined. There are only two string values that are defined, but false: the empty string, and the string containing the character 0, and nothing else. The first cannot happen - even an "empty line" ends with a newline. The latter can happen in two situations: for a file ending in "$/0", that is, the last line contains 0, and does not end with the line terminator. But regular text files always do (otherwise, they aren't proper text files anyway). The second case is if you read in the file character by character, by setting $/ = \1;, and the file contains a 0.

    If you have opened the file using a PerlIO filter, anything can happen (or if you have tied the file handle). But then, an undefined value may be returned as well, even if the file hasn't completely read.

Re^2: A refactoring trap
by ihb (Deacon) on Aug 23, 2005 at 21:47 UTC

    Dispite that many has pointed out that

    while (my $line = <DATA>) { ... } while (defined (my $line = <DATA>)) { ... }
    are identical, your first remark is true. The problem lies elsewhere:
    while (<DATA>) { ... }
    doesn't localize $_ and thus leaves $_ undefined after the loop.
    while (my $line = <DATA>) { ... }
    doesn't suffer from this as it doesn't touch $_.

    If put in a subroutine this innocent little bug cause a serious headache while trying to find out why $_ all of a sudden is undefined.

    ihb

    See perltoc if you don't know which perldoc to read!