in reply to Re: To Kill a Meme: while(defined($line = <>))
in thread To Kill a Meme: while(defined($line = <>))

Your post gives the impression that it's somehow wrong to be explicit,

That's certainly not what I hoped to convey.

As I said in a reply to Juerd, I relish the fact that I don't have to be explicit with everything, but that's a very different sentiment and I was addressing a very different point.

What I don't like about the whole while-defined-readline business is that most people use it without a clue why they are using it.

Maybe I should have chosen a less violent title. And perhaps, instead of ending the node with "please, try to lay this old habit to rest" I should have said, "if you don't know why you are doing it, don't bother." I really don't care half as much as some seem to think I do now. :-)

But just because it's no longer needed, it's not wrong, doesn't easily lead to mistakes (quite the opposite) nor is it misleading.

I mostly agree with that except that I think it does lead to mistakes. Not coding mistakes, but conceptual mistakes. When it is coded explicitly, it seems to indicate to perl beginners that it is necessary for a common case. Then they start imagining what that common case is and they get it all wrong but they don't know that. Then those assumptions bleed into other code they write.

-sauoq
"My two cents aren't worth a dime.";
  • Comment on Re: Re: To Kill a Meme: while(defined($line = <>))

Replies are listed 'Best First'.
Re: To Kill a Meme: while(defined($line = <>))
by Abigail-II (Bishop) on Nov 03, 2003 at 10:40 UTC
    I mostly agree with that except that I think it does lead to mistakes. Not coding mistakes, but conceptual mistakes. When it is coded explicitly, it seems to indicate that it is necessary for a common case.
    Well, generally, the defined test is necessary. The "common" case is the exception where Perl is providing the short-cut. If there is any danger, it's that people get used to writing while ($line = <>), and think that they can also write: while ($cond and $line = <>) or $line = <>; while ($line) {.... ; $line = <>}.

    Now, I don't think the danger is anything to worry about, but I've seen cases where the defined() test was missing where it should have been.

    Now, I'd be really interested in hearing what you think is the common case, and where people get it wrong by using defined ($line = <>).

    Abigail

      Now, I'd be really interested in hearing what you think is the common case, and where people get it wrong by using defined ($line = <>).

      The most common case is reading a text file which ends with a newline. And doing so without changing $/.

      What people get wrong is that they tend to think they need to check defined() because of blank lines. In other words, they get the mistaken impression that a scalar can contain a newline and be false.

      -sauoq
      "My two cents aren't worth a dime.";
      
        What people get wrong is that they tend to think they need to check defined() because of blank lines.

        Really? I've never encountered people thinking that. Why do you think people think this way? Have you ever seen code where people do:

        while ($line = <>) { ... }
        and expect it to read in just one paragraph, and not the entire file?

        Having said that, assuming you are right, it would be better to teach them the proper meaning of defined, instead of discouraging them not to used 'defined'.

        Abigail

      I've seen cases where the defined() test was missing where it should have been.

      I'm curious by what criteria you judge that it "should have been." Do you mean that it should be there as a matter of good defensive programming style? Or was there a real likelihood that an error would have resulted eventually? And, if so, what error?

      -sauoq
      "My two cents aren't worth a dime.";
      
        I'm curious by what criteria you judge that it "should have been." Do you mean that it should be there as a matter of good defensive programming style?

        Nothing to do with style, but with correctness. Stuff like:

        while (($line = <>) && $line =~ /\S/) { ... } while (($line1 = <>) && ($line2 = <>)) { ... }
        Also, the standard way of translating a while to a for(;;) loop won't work:
        for (;$line = <>;) { ... }
        And even:
        next unless $line = <>;

        They are all cases where a defined test should be used, because otherwise you may get unwanted effects.

        Abigail