in reply to Doubt on defined-ness

The condition will be false if $_ is undef or 0 or the empty string (or whatever else perl deems to evaluate to false.)

So, if your last line is not terminated by a newline and is the string "0", you'll get tripped on this if don't for defined-ness.

Update: Considering the discussion below, I should have made it clear that this is a potential problem only for if statements (which is what the OP asked about), not while statements.

What is interesting is that even though the condition expression for while and if statements is executed in "boolean" context, the magic of the diamond operator only happens in while statements.

use strict; use warnings; use Contextual::Return; use Carp; while (foo()) { last; } while (my $x = foo()) { last; } if (foo()) { } if (my $z = foo()) { } sub foo { return BOOL { carp "BOOL"; 1; } SCALAR { carp "SCALAR"; 1; } ; } __END__ BOOL at ./cr line 6 BOOL at ./cr line 7 BOOL at ./cr line 8 BOOL at ./cr line 9

Replies are listed 'Best First'.
Re^2: Doubt on defined-ness
by moritz (Cardinal) on Jun 18, 2008 at 19:19 UTC
    Actually I was about to answer just that, but then I tested it - and it turned out I was wrong.

    Consider this:

    $ hexdump -C foo 00000000 61 0a 30 |a.0| 00000003 $ perl -wle 'print "read line" while (my $x = <>)' foo read line read line $

    I have a file foo here with an 'a', a newline, and a '0' - no trailing newline.

    I'd expect just one line of output, because 0 is false. But why am I getting two lines? That doesn't seem to be logical to me.

    So I modified my test scrpt a bit:

    $ perl -MDevel::Peek -wle 'while (my $x = <>){ print "read line"; pri +nt "and its true" if $x }' foo read line and its true read line

    So, the second line evaluates to true in the while-condition, but not in the following if-condition. Is there some kind of special magic? If yes, where is it documented?

    Update ok, got it. Thank you all. I didn't realize it works for arbitrary variable names, and thought that $_ was special cased.

      It's because perl applies its magic to your while. Deparse shows it as
      while (defined(my $x = <ARGV>))


      Unless I state otherwise, all my code runs with strict and warnings
      It's just syntactic sugar. Perlop says:
             The following lines are equivalent:
      
                 while (defined($_ = <STDIN>)) { print; }
                 while ($_ = <STDIN>) { print; }
                 while (<STDIN>) { print; }
      
      
      So, the second line evaluates to true in the while-condition, but not in the following if-condition. Is there some kind of special magic? If yes, where is it documented?
      the only location where i found it mentioned after a quick search is in perlvar $_:
      $ARG $_ The default input and pattern-searching space. The following pairs are equivalent: while (<>) {...} # equivalent only in while! while (defined($_ = <>)) {...}
      edit: and in perlsyn
      edit: ah, it's in perlop, like betterworld mentioned. overlooked it.
Re^2: Doubt on defined-ness
by waldner (Beadle) on Jun 18, 2008 at 19:15 UTC
    Well, ok for the non-newline terminated lines (I hadn't thought about that case), but can really $_ be undefined after $_=<FH> if we are not at eof?