Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

True or False? A Quick Reference Guide

by bobf (Monsignor)
on Sep 29, 2005 at 04:38 UTC ( [id://495975]=perlmeditation: print w/replies, xml ) Need Help??

I wrote this quick reference guide for those times, late at night, when I forget how Perl treats various values. (After debugging a troublesome if(expression ) statement I occasionally rediscover that while both 0 and the empty string ('') are false, 0 eq '' is false but 0 == '' is true.) This meditation is not meant to be an in-depth discussion of the concept of truth, and the tables are not comprehensive. Nevertheless, I hope someone else finds this useful.

Truth and Falsehood

Identifying which values are treated as 'true' and which are treated as 'false' is straightforward once a few rules are established, but sometimes it is difficult to find exactly where in the docs a particular rule is documented. The following quotes summarize the main points to keep in mind (from the ActiveState docs for 5.6.1).

  • "A scalar value is interpreted as TRUE in the Boolean sense if it is not the null string or the number 0 (or its string equivalent, "0"). The Boolean context is just a special kind of scalar context where no conversion to a string or a number is ever performed." (from perldata)
  • "When used as a number, undef is treated as 0; when used as a string, it is treated the empty string, ""; and when used as a reference that isn't being assigned to, it is treated as an error." (from perlsyn)
  • "The while statement executes the block as long as the expression is true (does not evaluate to the null string "" or 0 or "0")." (from perlsyn)
The table below summarizes these rules. The text 'empty str' represents the empty string (""). The first test (if( $var )) reveals whether perl treats the value as true or false. The results of the next two expressions (if( defined $var ) and if( $var eq '' )) are fairly obvious, but they are included in the table to highlight the different interpretation of undef in each case. Finally, the expression if( $var == 0 ) tests the value's numeric equivalency to 0.

Truth tests for different values
Result of the expression when $var is:
Expression 1 '0.0' a string 0 empty str undef
if( $var ) true true true false false false
if( defined $var ) true true true true true false
if( $var eq '' ) false false false false true true
if( $var == 0 ) false true true true true true

Several common values were left out of the table in an effort to keep the size manageable. Those values include the following and are treated as noted (this is not an exhaustive list):

  • String zero ("0") is evaluated as numeric zero (0)
  • These values are interpreted as strings (like '0.0'):
    • '0E0' (exponential)
    • '00' (octal)
    • '0x0' (hexadecimal)
    • '+0' (positive), '-0' (negative)
    • ' 0' (spatial), '0\n' (linear)
    • '.0' (fractional), '0.' (periodic)
    See tye's poll, The best "true zero" is..., for others.

Logical Tests: AND, OR

Using the table and rules above, the outcome of a logical AND or a logical OR test can be predicted. In Perl these operators do not simply return 0 or 1, however. Instead, they return the last value that was evaluated in the expression, which is usually only tested for truth (using the table and rules given above) so the actual value is ignored. Due to the short-circuiting nature of the operators, the returned value can be either the first or last value in the expression. This behavior is documented in perlop:

  • "Binary ``&&'' performs a short-circuit logical AND operation. That is, if the left operand is false, the right operand is not even evaluated."
  • "Binary ``||'' performs a short-circuit logical OR operation. That is, if the left operand is true, the right operand is not even evaluated."
  • "The || and && operators differ from C's in that, rather than returning 0 or 1, they return the last value evaluated."
The tables below list the return value for logical AND (&&, and) and logical OR (||, or) operations for the values tested above. The values are colored according to whether they are interpreted as true or false (as given in the table above). In these tables, 'a string' has been replaced by 'A string' and 'B string' so it is clear which value is returned.

Logical AND tests for different values: A && B
Value of B
Value of A 1 '0.0' B string 0 empty str undef
1 1 0.0 B string 0 empty str undef
'0.0' 1 0.0 B string 0 empty str undef
A string 1 0.0 B string 0 empty str undef
0 0 0 0 0 0 0
empty str empty str empty str empty str empty str empty str empty str
undef undef undef undef undef undef undef

Logical OR tests for different values: A || B
Value of B
Value of A 1 '0.0' B string 0 empty str undef
1 1 1 1 1 1 1
'0.0' 0.0 0.0 0.0 0.0 0.0 0.0
A string A string A string A string A string A string A string
0 1 0.0 B string 0 empty str undef
empty str 1 0.0 B string 0 empty str undef
undef 1 0.0 B string 0 empty str undef

Exclusive OR: XOR

The result of an XOR expression (minimally documented in perlop) can also be predicted using the truth table given above. The following table summarizes the results for the values tested above.

Logical XOR tests for different values: A xor B
Value of B
Value of A 1 '0.0' a string 0 empty str undef
1 false false false true true true
'0.0' false false false true true true
a string false false false true true true
0 true true true false false false
empty str true true true false false false
undef true true true false false false

References

Thanks to tye, castaway, GrandFather, and Detonite for their pre-post comments.

Updates:

  • Changed the AND and OR tables to more clearly show which value is returned, per Skeeve's suggestion.
  • Minor rewording to make it more clear that the rules are quoted directly from the Perl docs, per Anonymous Monk's comments.
  • Updated legacy HTML syntax

Replies are listed 'Best First'.
Re: True or False? A Quick Reference Guide
by Zaxo (Archbishop) on Sep 29, 2005 at 05:32 UTC

    bobf++, well done.

    There is another logical operator; I like to regard the sequence operator, scalar comma, as the unconditional logical operator. The right hand argument is evaluated regardless of the truth of the already-evaluated left, and the last evaluated value is returned. Naturally, this has more use in shoehorning several evaluations into a single expression than in pure logic. It's often useful that way in the body of modifier statements like s/foo/bar/g, print for <>;.

    Used where logicals are often seen, sequence expressions can be a sort of front-loaded continue block - without introducing a scope.

    my ($i, $j) = (1, 10); while ($i++, $j--, $i < $j) { print "$i\t$j\n"; } __END__ 2 9 3 8 4 7 5 6
    Note that increment and value of a variable in one expression are ok with C if they are seperated by the comma operator. That seems to work in Perl, too, as is sort-of-documented.

    I think that that view of the sequence operator is not the usual one, but I find it useful. If there were an ultra-low precedence version like and and or, I'd call it then.

    After Compline,
    Zaxo

Re: True or False? A Quick Reference Guide
by xdg (Monsignor) on Sep 29, 2005 at 10:15 UTC

    It's worth mentioning this tidbit I picked up from HOP: '0 but true' is a special-case that will not issue a warning when used in a numeric context.

    $ perl -we 'print "0 but true" + 2' 2 $ perl -we 'print "0 but actually true" + 2' Argument "0 but actually true" isn't numeric in addition (+) at -e lin +e 1. 2

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      Interesting. I wasn't aware of "0 but true" being special cased. But you did realize that strings matching /^0E\d+$/ have this property too right?

      D:\>perl -lwe "my @b=(0,1); for (qw(0E0 1E0)) { print; print qq(Bool:) +,$b[!!$_]; print qq(0+:),0+$_; print $/; }" 0E0 Bool:1 0+:0 1E0 Bool:1 0+:1
      ---
      $world=~s/war/peace/g

        Yes, though that's a little more logical, since perldata specifies that numbers can be written in scientific notation in a form like 12.34E-10. So 0E0 is just a number, and "0E0" is a string that has length (is true) but evaluates as 0E0, which is zero (false). If you want to think about it the other way, '0' is a special case of a string that has length but is treated as false.

        What I find interesting about "0 but true" is that it more clearly highlights to a reader that something unusual is going on than something like "0.0" or "0E0" -- and to such an extent that it was excepted from the usual warnings so as to make it easier to use that way. Anyone know the history of this? Or what version of Perl it first appeared in? (timtoady, are you out there?)

        -xdg

        Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: True or False? A Quick Reference Guide
by Juerd (Abbot) on Sep 29, 2005 at 12:23 UTC

    A quicker reference ;)

    0/FALSE: 0, "0", "", undef 1/TRUE: everything else AND OR XOR NOT 0&0=0 0|0=0 0^0=0 !0=1 0&1=0 0|1=1 0^1=1 !1=0 1&0=0 1|0=1 1^0=1 1&1=1 1|1=1 1^1=0 & | ^ ~ <-- bitwise && || ! <-- logical, high precedence and or xor not <-- logical, low precedence

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

      Perl 6:

      0/FALSE: 0, "0", "", undef ("0" is true if the type is Str) 1/TRUE: everything else AND OR XOR NOT +& +| +^ +^ <-- bitwise, numeric ~& ~| ~^ ~^ <-- bitwise, string ?& ?| ?^ ?^ <-- bitwise, boolean && || ^^ ! <-- logical, high precedence and or xor not <-- logical, low precedence
      • The difference between logical and bitwise boolean is that logical AND and OR return an operand, while bitwise AND and OR return boolean values (the original values are lost).
      • ?^/^^, and ?^/! are practically the same.
      • ^^ was missing in Perl 5.
      • +^, ~^, ?^ are both XOR and NOT, depending on whether they are used infix (in between) or prefix (in front).

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

Re: True or False? A Quick Reference Guide
by Skeeve (Parson) on Sep 29, 2005 at 09:10 UTC
    Well done, ++ from me too.

    One enhancement I think you should add: In the && and || tables use instead of "a string" "A string" and "B string" to reflect which of the both is the result of A && B and A || B.

    $\=~s;s*.*;q^|D9JYJ^^qq^\//\\\///^;ex;print
Re: True or False? A Quick Reference Guide
by Anonymous Monk on Sep 29, 2005 at 11:05 UTC
    A scalar value is interpreted as TRUE in the Boolean sense if it is not the null string or the number 0 (or its string equivalent, "0"). The Boolean context is just a special kind of scalar context where no conversion to a string or a number is ever performed. (see perldata)

    I know what you mean by the null string, but not every one does, specially not the people who need a reference. Perl doesn't have the concept of null, and we avoid using the term null string, because it's not always clear what is meant by it, the empty string, or an undefined value.

    Having said that, you only list three things that are false in boolean context: the empty string (null string), the number 0, and the string "0". But you left out the most important one: the undefined value. But there are more, here's a (hopefully) complete list:

    • The undefined value.
    • The number 0.
    • The empty string.
    • The string "0".
    • An empty array.
    • An empty hash.
    • Objects with appropriate overloaded boolean value.

    When used as a number, undef is treated as 0; when used as a string, it is treated the empty string, ""; and when used as a reference that isn't being assigned to, it is treated as an error.

    Well, there's also auto-vivification.

    The while statement executes the block as long as the expression is true (does not evaluate to the null string "" or 0 or "0"). (see perlsyn)

    I wonder why you mention while, but not for(;;) or until. Having said that, your statement is close, but not completely true. The block can also be exited with a last, return, goto, die or even a next LABEL_TO_OUTER_BLOCK statement. Furthermore, if the condition becomes false during execution of the block, the execution isn't stopped - checks are only done before entering the block. Finally, there's

    do { ... } while (0);
    which will execute the block at least once, even if the condition is never true.
Re: True or False? A Quick Reference Guide
by rvosa (Curate) on Oct 01, 2005 at 13:12 UTC
    ++ this should be a tutorial. Very good.
Re: True or False? A Quick Reference Guide
by KurtSchwind (Chaplain) on Mar 09, 2015 at 13:12 UTC

    I've referenced this post a lot because it's so well organized. It's the easiest way for me to explain 'truthiness' to someone new to perl. I regret that I can only upvote this once. And on that topic:

    "Reputation: 213 (+220 -7)"
    7 downvotes? Who could downvote this?

    --
    “For the Present is the point at which time touches eternity.” - CS Lewis
      > I regret that I can only upvote this once.

      Actually your reply already pushed it up to 216! :)

      > 7 downvotes? Who could downvote this?

      False and untrue people? ;-D

      Well honestly a 0.3 percent error shouldn't worry you and the html-formatting has some issues...

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)

      PS: Je suis Charlie!

        I stopped by the Monastery while on a sabbatical and, thanks to your post, found that my once well-formed HTML had degraded into legacy syntax. As I am not familiar with current HTML/CSS conventions, I removed the offending tags to get rid of the errors. (I'd welcome formatting suggestions from anyone that can offer them...)

        Thanks for alerting me to the issue. Problem fixed (for now).

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://495975]
Approved by Zaxo
Front-paged by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (6)
As of 2024-03-28 20:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found