Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

Re: A refactoring trap

by redlemon (Hermit)
on Aug 17, 2005 at 07:34 UTC ( #484330=note: print w/replies, xml ) Need Help??

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>)) { ... }


Replies are listed 'Best First'.
Re^2: A refactoring trap
by wolv (Monk) 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


    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".


        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.


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

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://484330]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (6)
As of 2020-08-10 12:01 GMT
Find Nodes?
    Voting Booth?
    Which rocket would you take to Mars?

    Results (57 votes). Check out past polls.