--- name: truthiness in Perl --- # Truthiness Before logic, the values logic operates on. Perl does not have a dedicated boolean type. Every scalar is either *true* or *false* when used in boolean context, and the rule is short: > A scalar is **false** if it is one of the four values > `undef`, the integer `0`, the string `""`, or the string `"0"`. > Everything else is **true**. Four false values, every other scalar — including the strings `"00"`, `"0.0"`, `"0E0"`, and `"false"` — is true. ```perl if (0) { ... } # false -- the integer zero if (0.0) { ... } # false -- numerically zero if ("") { ... } # false -- empty string if ("0") { ... } # false -- the string "0" if (undef) { ... } # false -- undefined value if ("00") { ... } # TRUE -- non-empty, not the string "0" if ("0.0") { ... } # TRUE -- non-empty, not the string "0" if ("0 but true") { ... } # TRUE -- non-empty, not the string "0" if (" ") { ... } # TRUE -- single space is non-empty if ("false") { ... } # TRUE -- it's just a 5-character string ``` The `"0 but true"` idiom is not a joke. Some Perl APIs return a value that must compare equal to zero numerically (so an arithmetic test does the right thing) but be true in a boolean context. The classical case is `ioctl()` — success returning literally zero would test false. The string `"0 but true"` is numerically zero (with a warning suppressed by historical agreement) and boolean-true because it is not in the four-element false set. ```perl my $rc = ioctl($fh, $cmd, $buf); $rc == 0 and warn "numeric zero"; # would fire on success $rc or warn "boolean false"; # FIRES if API returned 0 # but NOT if "0 but true" ``` ## Two flavours of comparison Perl has parallel families of comparison operators because it has parallel notions of equality. Numbers compare numerically; strings compare lexically. The wrong family on the wrong type is one of the most common bugs in beginner Perl. | Test | Numeric | String | |--------------------|---------|--------| | equal | `==` | `eq` | | not equal | `!=` | `ne` | | less than | `<` | `lt` | | greater than | `>` | `gt` | | less or equal | `<=` | `le` | | greater or equal | `>=` | `ge` | | three-way (sort) | `<=>` | `cmp` | `==` on strings always succeeds for any two non-numeric strings — both convert to `0`, and `0 == 0` is true: ```perl "foo" == "bar"; # TRUE -- both stringify to numeric 0 "foo" eq "bar"; # FALSE -- the actual question "10" eq 10; # TRUE -- string "10" equals numeric 10 stringified "10" == 10; # TRUE -- 10 == 10 numerically "10" lt "9"; # TRUE -- lexical: "1" < "9" "10" < "9"; # FALSE -- numeric: 10 > 9 ``` `<=>` and `cmp` return `-1`, `0`, or `+1` — the standard sort comparator shape. They are not boolean operators in the strict sense, but they appear inside boolean contexts often enough that you should know them. ## Why this matters for logic Every boolean operator in Perl — `&&`, `||`, `//`, `!`, `xor`, `and`, `or`, `not` — uses the four-value false set above as its input rule. Whenever a chapter below says "if `$x` is false", that is exactly what is meant: `$x` is `undef`, `0`, `""`, or `"0"`. Whenever it says "if `$x` is true", `$x` is anything else. Two consequences worth keeping in mind: 1. **A scalar can be true without being a boolean true value.** Strings, references, blessed objects, large numbers — all true. When you ask "is this true?" you are not asking "does this equal 1?" — you are asking "is this not in the false set?". 2. **The result of a boolean operator is not always 1 or 0.** The next chapter covers this in detail. Briefly: `&&` and `||` return one of their *operands*, not a normalised boolean. This is a feature, not a quirk, and many Perl idioms depend on it.