Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Truth and Falsehood

by haukex (Chancellor)
on Aug 17, 2019 at 09:19 UTC ( #11104607=perlmeditation: print w/replies, xml ) Need Help??

Truth and Falsehood

In Perl, the following values are false in boolean context:

  • The number zero (0)
  • The string "0"
  • The empty string ""
  • undef

All other values are true.

Boolean context is a scalar context. Therefore the following things, when evaluated in boolean/scalar context, are also false:

  • An empty array, which evaluates to the number of elements it contains, i.e. zero (0).
  • An empty hash, which evaluates to a false value when it is empty.
  • The empty list (), which evaluates to undef.

A true value negated by ! or not, plus many of Perl's builtins/operators, return a special false value: When evaluated as a string it is treated as "", but as a number, it is treated as 0, without causing any warnings.

When the Perl documentation says that a operator or function returns "a false value" or "a true value" (or more simply, "false" or "true"), it may return any of the above values.

Related Topics

Context

If you are unsure about Perl's concept of context, see e.g. the Context tutorial, the section "Context" in Chapter 2 of the Camel, or the section "Context" in Modern Perl.

Definedness

To test whether a value is undef or not, use defined. Note that "false" values like the empty string "" or the number 0 are still defined.

Existence of Hash Keys

To test whether a hash contains a certain key or not, use exists. Note that a key can exist in a hash, but the value stored for that key can be undef. If you attempt to access a hash key that does not exist, Perl will also return undef, which is why the distinction between defined and exists is important. To remove a key from a hash, use delete.

String Length

To get the length of a string, use length. For example, the test if (length $string) allows you to differentiate between "0" and "", which would otherwise both be false. Note: As of Perl 5.12, if you give the length function an undef value, it will return undef without producing a warning, which is helpful in boolean tests. (In Perl versions before 5.12, length would produce a warning when given undef.)

Hash and Array Size

To get the size of an array, use scalar, as in scalar @array, or use the array in a scalar context, for example my $size = @array;. To test whether an array is empty or not, simply use it in a boolean context, such as if (@array). (Note: $#array returns the index of the last element of the array, so it is not the same - see perldata for details.)

If a hash is empty, using the hash in scalar/boolean context (e.g. if (%hash)) will return a false value, regardless of the Perl version. To portably get the number of keys in a hash, use keys in a scalar context, as in scalar keys %hash or my $size = keys %hash;. As of Perl 5.26, it is also possible to say scalar %hash directly to get the number of keys (previous versions of Perl would return some internal information about the hash: the number of used buckets and the number of allocated buckets).

Numerically Zero, But True

In a few special cases, Perl functions may wish to return the number zero, but want to do so in a way that this value is still "true" when tested in a boolean context. For example, this could be to indicate that an operation was successful, but its return value is zero. Two common ways to do this are for the function to return the strings "0E0" or "0 but true", which are both "true" under the above rules, but when used as a number, are zero. (The string "0 but true" is special-cased in Perl to not produce warnings about it not looking like a number.)

Overloading

As a special case, an object may choose to change its behavior for different operations, such as boolean context. So for example, normally if ($object) would return true, since in the normal case a reference is a true value, but in the presence of overloading, if ($object) may be false. Authors of classes are generally advised to use this feature in a way that makes the code DWIM (Do What I Mean). (You may disable overloading with no overloading;, although in that form it will disable all overloading.)

Edits: Minor clarifications. Added section on overloading, thanks Tux! Updates according to jcb's reply, thanks!

This node is to replace the "Truth and Falsehood" section that used to be in perlsyn, but was merged into a much longer text in perldata (and is now harder to link to explicitly, IMHO).

Replies are listed 'Best First'.
Re: Truth and Falsehood
by hippo (Chancellor) on Aug 17, 2019 at 10:09 UTC

    Thanks for this useful node.

    • An empty array, which evaluates to the number of elements it contains, i.e. zero (0).
    • An empty hash, which evaluates to a false value when it is empty.

    I've tested empty hashes on several perls here and they, like empty arrays, always appear to evaluate to zero as well. Is there a reason why you have expressed them differently here?

      I've tested empty hashes on several perls here and they, like empty arrays, always appear to evaluate to zero as well. Is there a reason why you have expressed them differently here?

      Just because that's what the Perl documentation says. perldata:

      If you evaluate a hash in scalar context, it returns a false value if the hash is empty. If there are any key/value pairs, it returns a true value.

        I see - thank you. Interestingly the very next sentence in perldata is:

        A more precise definition is version dependent.

        which suggests that there may be some versions out there where the false value returned is not zero (or that there may be in future, intriguingly). I'll have to try to remember only to test the truth of empty hashes rather than their numerical value. :-)

Re: Truth and Falsehood
by jcb (Hermit) on Aug 17, 2019 at 22:38 UTC

    While I know that you did not label this "[RFC]", this looks like a good draft for a brief tutorial.

    As currently written, this neglects $#array. I think it would be better to write the first paragraph in "Hash and Array Size" as:

    To get the number of elements in an array, use scalar, as in scalar @array, or use the array in a scalar context, for example my $size = @array;. To test whether an array is empty or not, simply use it in a boolean context, such as if (@array). To get the largest index in an array, use $#array. To explicitly resize an array, assign a value to $#array. Perl normally grows arrays as needed, but explicitly assigning to $#array can also shrink an array, discarding elements from the high end.

    I have tried to follow your style in the above text, but I expect that you will further edit that before using it, if you use it.

    The exists and defined tests also apply to array indexes, in the same way that they apply to hash keys. This can be explained briefly and would go well with adding mention of $#.

    And one minor stylistic quibble: I think of exceptions as "thrown" with die because they can be "caught" with eval BLOCK, but can warnings be similarly "caught" in Perl or would it be better to say that length returns undef without producing a warning?

      While I know that you did not label this "[RFC]", this looks like a good draft for a brief tutorial.

      The intent was a little different, as I mentioned at the very bottom of the node: There used to be a section "Truth and Falsehood" in perlsyn that was nice and short, and easy to link to whenever someone's question touched on Perl's concept of true/false, but that section was merged into a much longer block of text in perldata, which IMHO makes it harder to provide a link to people who just want to know about that one topic. (The title is such that it's easy to link to as [Truth and Falsehood].) So I want to keep the main point of the node focused on just true/false, hence I tried to separate out the "Related Topics" so that the top is just a "TL;DR".

      As currently written, this neglects $#array.

      Yes, that's a good point, I'll add a brief mention of it, thanks. IMHO, the more detailed description you wrote starts getting a little off-topic to the main point of the node, so I'll keep it a little shorter.

      The exists and defined tests also apply to array indexes

      Not entirely; from exists:

      WARNING: Calling exists on array values is strongly discouraged. The notion of deleting or checking the existence of Perl array elements is not conceptually coherent, and can lead to surprising behavior.
      would it be better to say that length returns undef without producing a warning?

      Yes, good point, thanks!

        the more detailed description you wrote starts getting a little off-topic

        Fair enough, and the link to the reference manual makes up for trimming it.

        [for exists on arrays]

        The tests apply, even though the results can be surprising, mostly due to the fact that Perl's arrays have a contiguous range of index values. I suspect that exists $array[$i] is equivalent to $i <= $#array. If not, then that is really surprising and probably better left "under the rug". :-)

Re: Truth and Falsehood
by ikegami (Pope) on Aug 18, 2019 at 06:29 UTC

    The empty list (), which evaluates to undef.

    When's the last time you did if (()) {}? Why would you ever do that?

    I suppose one could use sub f { return (); } if (f()) {}, but that's a very bad practice. (A sub that's expected to return a scalar should do so even in list context.)

    So I'm rather baffled as to why this was mentioned. There are so many operators that can return false that would merit a mention before (), such as scalar assignment, list assignment, grep, map, m// and s///.

      I suppose one could use sub f { return (); } if (f()) {}, but that's a very bad practice. (A sub that's expected to return a scalar should do so even in list context.)

      I agree that subs that are expected to return a scalar should do return undef because of the problems with my %hash = ( k => f() );, but there are also some good arguments against return undef in other cases - as you've said, there are exceptions.

      I mostly mentioned it because the old section "Truth and Falsehood" mentioned it, although with an attempt to improve the wording, as you've suggested yourself in the past.

      Update: I missed your ninja edits, but I hope I've cleared up your bafflement nonetheless. Please feel free to add any information you think is missing!

      Logically, operators like grep, map, m//, and s/// all return false by returning an empty list, at least in a simple description.

        That makes no sense. An empty list isn't false. Or true. It's not a scalar, so those concepts don't apply to it. You can't evaluate whether an empty list is true or false. You can only evaluate if a scalar is true or false.

        As such, if you're trying to get a true or false value from those operators, you would be evaluating them in scalar context, and the following is what the listed operators actually return in scalar context:

        • grep returns the count of matching elements.
        • map returns the count of elements it would return.
        • m// and s/// return success or not.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (10)
As of 2019-09-17 10:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    The room is dark, and your next move is ...












    Results (207 votes). Check out past polls.

    Notices?