http://qs1969.pair.com?node_id=999577


in reply to Re: What is true and false in Perl?
in thread What is true and false in Perl?

Another one that's false is a list of undefs. An array of undefs though is true.
if ( (undef,undef) ) { } # a list of undefs is false @arr = (undef,undef); if ( @arr ) {} # an array of undefs is true
We make use of this like so:
$_ = 'x'; if (($a,$b) = m/(.)(.)/) { }
mc0e

Replies are listed 'Best First'.
Re^3: What is true and false in Perl?
by tobyink (Canon) on Oct 18, 2012 at 02:26 UTC

    That's not quite true. Observe:

    # Does not say "true". This is as you describe. say "true" if undef, undef; # Still doesn't say true. say "true" if 1, 2, 3, 4, undef;

    The reason for this behaviour is that if imposes a scalar context on the expression that acts as its condition. When the comma operator is used in a scalar context it is not a list constructor and instead evaluates the left argument, discards it and then evaluates the right argument (it basically acts like the semicolon but with a different precedence).

    Thus this:

    say "true" if 1, 2, 3, 4, undef;

    Is essentially the same as:

    sub x { 1; 2; 3; 4; return undef; } say "true" if x();
    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
Re^3: What is true and false in Perl? (undef,undef)
by tye (Sage) on Oct 18, 2012 at 03:50 UTC

    It isn't a list nor an array in scalar context that your example is making use of. It is a list assignment (in scalar context).

    A list assignment in scalar context returns the number of items in the right-hand list.

    And, in your example, 'x' =~ m/(.)(.)/, in a list context, returns an empty list, not a list of two 'undef's. An empty list (on the right-hand side of the list assignment) contains zero items so the assignment in scalar context returns 0, which is one of the documented false values.

    But there is a kernel of truth hidden behind your mistakes.

    There have been some exceptions (as near as I can remember, on an inconsistent basis) to the rule about what a list assignment returns in scalar context. Those exceptions were meant to handle cases very similar to what you described.

    sub undefs { my( $count ) = @_; return ( undef ) x $count; } if( my( $x, $y ) = undefs(2) ) { print "true\n"; } else { print "false\n"; }

    In some versions of Perl, that code would print "false". In the relatively modern Perl I had handy, it prints "true".

    I even recall having a very short on-line conversation with Larry years ago about what I considered to be bugs such as ( undef, undef )[0] being an empty list instead of being a list containing a single 'undef' and he was worried about breaking the fact that the above code was supposed to print "false". I argued that that wasn't a feature worth keeping.

    But I didn't follow-up to see what decisions were made back then. And, just now, I didn't test the current behavior except minimally. I think there was at least one thread about this stuff on PerlMonks around the time Larry and I talked, but I haven't looked for it. It might've just been in the chatterbox.

    - tye        

      Hi can somebody explain to me the reason behind the following: test.pl: #!/usr/bin/perl my $a = (1==0); print "__".ref($a)."__\n"; Output: ____

        What do you think ref does?

        In your example code, $a doesn't contain a reference. It contains a false value. ref does exactly this: "Returns a non-empty string if EXPR is a reference, the empty string otherwise."


        Dave

Re^3: What is true and false in Perl?
by jdporter (Paladin) on Oct 17, 2012 at 19:43 UTC
    print "true" if "IS" eq "evaluates to in scalar context"; # doesn't pr +int.
      what are you trying to say?

        The same thing tobyink and tye said, though more obtusely and snarkily.

        Here's another example:

        tie my $var, 'Some::BlackBox::Module'; $var = "45"; if ( $var ) { print "var is true\n" } # doesn't print! WTF?

        The mere fact that an expression evaluates to a true value in scalar context doesn't mean it is true.

        tie and overload are among the user-accessible features which can muddy the true/false waters.

        An example like this should make the principle more obvious:

        my $obj = ObjectWithLotsOfOpaqueStructure::AndLotsOfHiddenState->new( -use_overloading => 1, ); if ( $obj ) { print "obj is 'true'.\n"; # What does this even mean? # Maybe obj is an iterator with another available item? }