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

Whenever you use while (my $line = readline $fh), perl always adds defined if you haven't done so already. I think that this inconsistency between code and the ops that are actually executed is worse and causes people unfamiliar with Perl to think the program will not give that last blank or 0 line.

I am used to writing while (defined(my $line = readline $fh)) and will continue to write it like this. It does not cause any bug, what it does is crystal clear and the 9 extra characters won't hurt anyone.

Whenever I see the defined thing missing, I add it for clarity.

I read your post a couple of times, but the only argument I see for getting rid of "defined" is that it is not necessary. I'd understand your plea if defined would cause strange bugs, but it doesn't. It usually prevents them. Do you think we should also forget all about whitespace as well, just because it is not necessary?

And here we are. Years later and defined has been typed much more often in conditionals to avoid warnings than together with while. Those warnings ("Use of uninitialized value") are there for a reason. The very same reason that testing for definedness is usually a GOOD idea. It usually takes less than a second to type, and saves a lot of time when debugging. Perl's adding defined automatically to while is for me not a reason to not use it.

Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Replies are listed 'Best First'.
Re: Re: To Kill a Meme: while(defined($line = <>))
by sauoq (Abbot) on Nov 03, 2003 at 09:26 UTC
    It usually prevents them.

    Usually, it doesn't do anything.

    Even in the cases where the while doesn't check for definedness, like when you add something to the loop condition, it still usually doesn't do anything.

    In order for it to do anything at all, you have to be either A) using a perl <= 5.00404 or B) doing something more complex in your while loop than a simple assignment from a filehandle read and one of the following must be true: 1) you are reading fixed length one character records and you retrieve a record containing a single '0', 2) you have set $/ to a string containing one '0', or 3) the last line of a file you are reading must contain a single '0' and not be terminated with $/.

    If you need to code defensively for those conditions, go right ahead. Most people don't most of the time.

    Besides, you seem to have a good understanding of why you add it. Many don't. Many people write it that way because they have the vague notion that they need to for some reason. They don't add it for clarity.

    I, for one, think it does very little to add clarity. I think that seeing code with an explicit defined() like that has caused people unfamiliar with Perl to think the program will not give that last blank or 0 line when the explicit defined() is missing. This is confusing because, in %99.99 of the cases, the definedness check doesn't matter at all regardless of whether it is implicit or explicit. The program would go merrily on its way if the check didn't even exist.

    As theorbtwo said in another post, some people are of the mind that being explicit is always better. I do understand that train of thought even if I've rarely taken it to the extreme of spelling out r-e-a-d-l-i-n-e. There are some benefits to being explicit but I think that being explicit all of the time just for the sake of — well, for the sake of being explicit — misses the point.

    One of my favorite things about Perl is that I don't have to be explicit. That's a welcome relief from the languages I started out with.

    It's great to be able to think about the parts of a problem that interest me and to let perl take care of the parts that don't. Sure, I've got to know enough about Perl to fix things when problems arise. And I do. But, in practice, relatively few problems have come up as a result of perl not handling its parts intuitively. With Perl, a much higher proportion of my debugging time is spent on higher level problems than with languages where being explicit is a requirement, not an option.

    With Perl's expressive power, code can be focused tightly on the problem and elegant and succinct solutions are normal. I don't see any reason to dilute code by being explicit about such minor things as definedness checks when it just isn't necessary.

    Edit: The anonymonk post below is absolutely correct, and I have no excuse other than fatigue. I've edited the text above for correctness.

    -sauoq
    "My two cents aren't worth a dime.";
    

      Usually, it doesn't do anything. (...) In order for it to do anything at all, you have to be either A) using a perl <= 5.00404 or B) doing something more complex in your while loop than a simple assignment from a filehandle read and one of the following must be true: 1) you are reading fixed length records and retrieve a record containing all '0's, 2) you have set $/ to a string of one or more '0's, or 3) the last line of a file you are reading must contain a string of one or more '0's and not be terminated with $/.

      So by routinely adding 9 characters that are easy to remember, I no longer have to remember these 6 permutations that I will probably forget again within the next hour.

      Just like how by using strict, I don't have to remember that undeclared variables are implicitly global.

      I do not mind typing a little more if that means that I can forget a lot and get away with it.

      Especially since the extra code cannot introduce a bug, but only prevent obscure ones, please let me and the rest of the world type "defined". Perl thinks it is needed too: it adds the test in case you forget it. That's how important perl thinks it is, and I agree with perl. I agree strongly enough to explicitly use that "defined".

      I wish everyone continues to use defined. I hope that tutorials and books will continue to preach it, even when it isn't necessary. This is just like "use strict;" in many ways: the extra keystrokes prevent bad things.

      I sincerely hope that not too many beginners read your post, and that people who already know Perl well are sane enough to evaluate and then disregard it.

      How do you feel about the "return" statement as the last statement in a sub? I like it and use it whenever I can (i.e. when the sub is not an lvalue-sub), even though Perl implicitly returns the last evaluated expression anyway.

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

      1) you are reading fixed length records and retrieve a record containing all '0's, 2) you have set $/ to a string of one or more '0's, or 3) the last line of a file you are reading must contain a string of one or more '0's and not be terminated with $/.

      Not to be too pedantic, but you keep saying "a string of one or more '0's", when it is only a string of a single zero that evaluates as false.