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

roho has asked for the wisdom of the Perl Monks concerning the following question:

I just finished tracking down a very elusive bug in my code. The bug was caused by two defined's side by side (a copy/paste error). Perl doesn't object at either compile time or at run time, but two defined's reverses the logic of the expression. In the sample code below the first "if" statement is False (as expected), but the second "if" statement is True because of the two defined's.

I suppose there may be a use case somewhere where the result of one "defined" is fed into another, but my first reaction was that this is a bug. What do other monks think about this? Is this a bug in Perl or a "feature"?

#!/usr/bin/perl use strict; use warnings; my $x; if (defined $x) { print "True\n"; } else { print "False\n"; } if (defined defined $x) { print "True\n"; } else { print "False\n"; }

"Its not how hard you work, its how much you get done."

Replies are listed 'Best First'.
Re: defined defined -- Bug or "Feature"?
by dave_the_m (Monsignor) on Dec 24, 2015 at 07:45 UTC
    defined($x) returns a false, but defined value, so defined(defined($x)) is true.

    Dave.

      You state that like you know it to be the case, but I couldn't see that behavior described in the documentation. Do you know this from the code?

      Premature optimization is the root of all job security
        The docs say that it returns a boolean value, i.e. a true or false value. It would be surprising for a false value to also be undefined, as you would get 'undefined' warnings if you tried using operators on the results. This shouldn't warn:
        $x = defined($y) ^ defined($z);

        Dave.

        I guess he didn't (guess). It's easily tested...
        print defined( undef ) // 'n/a'; print defined( undef ) || 'n/a'; n/a
Re: defined defined -- Bug or "Feature"?
by GrandFather (Saint) on Dec 24, 2015 at 07:56 UTC

    The most likely answer is that defined returns an empty string as a false value. An empty string is defined so the left most defined sees a defined value - the result from the right most defined.

    So, not really a bug, just an interesting edge case.

    Premature optimization is the root of all job security
      Probably not, Pl_sv_false ought to be same as undef, there were some bugs regarding this, but i'm afk & my mem is fuzzy. Devel::Peek...:)
        PL_sv_undef, PL_sv_no and PL_sv_yes are three distinct values with distinct properties. Only PL_sv_undef is undef.

        Dave.

Re: defined defined -- Bug or "Feature"?
by dsheroh (Monsignor) on Dec 24, 2015 at 08:39 UTC
    two defined's reverses the logic of the expression
    No, it doesn't reverse the logic. It's always true, regardless of the single defined's result:
    $ perl -E 'say ((defined $x) ? "defined" : "undef")' undef $ perl -E 'say ((defined defined $x) ? "defined" : "undef")' defined $ perl -E '$x = 1; say ((defined $x) ? "defined" : "undef")' defined $ perl -E '$x = 1; say ((defined defined $x) ? "defined" : "undef")' defined
    This is because, as stated in previous comments, the first (rightmost) defined will always return a defined result, so the second (leftmost) defined always receives a defined input value.
Re: defined defined -- Bug or "Feature"?
by Anonymous Monk on Dec 24, 2015 at 10:23 UTC

    perlsyn:

    Truth and Falsehood

    The number 0, the strings '0' and "" , the empty list (), and undef are all false in a boolean context. All other values are true. Negation of a true value by ! or not returns a special false value. When evaluated as a string it is treated as "", but as a number, it is treated as 0. Most Perl operators that return true or false behave this way.

    I'm assuming this is the missing piece of documentation that explains why defined always returns a defined value.