Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

There's "0 but true", but is there "42 but false" in perl?

Tags:

exit-code

perl

As per the question. I know there's "0 but true" which is true in a boolean context but false otherwise, but can return something false in a boolean context but with a non-zero value (the obvious place for this is return statuses where 0 is success and anything else is an error).

like image 938
Clinton Avatar asked Jan 13 '23 15:01

Clinton


1 Answers

No. (Except for fun with dualvars and overloaded objects)

The truthiness of a Perl scalar depends primarily on the string value. If no string value is present, the numeric field will be used.

False values are: undef, "", 0, and to avoid issues by testing the stringification first: "0".

Not everything that is numerically zero evaluates to false: "0E0" is true, so is the more self-documenting "0 but true". The latter is special-cased to avoid non-numeric warnings.

However, enter dualvars. The numeric and stringy field of a scalar don't have to be in sync. A common dualvar is the $! variable that is the errno in numeric context, but a error string containing a reason as a string. So it would be possible to create a dualvar with numeric value 42 and string value "", which will evaluate to false.

use Scalar::Util qw/dualvar/;

my $x = dualvar 42, "";
say $x;   # empty string
say 0+$x; # force numeric: 42
say $x ? 1 : 0; # 0

And then overloaded objects. Instances of the following class will stringify nicely, but still evaluate to false in a boolean context:

package FalseString;
sub new {
  my ($class, $str) = @_;
  bless \$str => $class;
}
use overload
  '""'   => sub { ${shift()} },
  'bool' => sub { 0 };

Test:

my $s = FalseString->new("foo");
say $s;
say $s ? "true" : "false";

Prints

foo
false
like image 123
amon Avatar answered Jan 28 '23 06:01

amon