How do I use boolean variables in Perl?
Asked Answered
S

10

244

I have tried:

$var = false;
$var = FALSE;
$var = False;

None of these work. I get the error message

Bareword "false" not allowed while "strict subs" is in use.
Shallop answered 24/6, 2009 at 4:8 Comment(2)
You might want to start with my book Learning Perl. It's easier than guessing what to do until you get it right (monkeys, typewriters, and Hamlet, and all that). :)Decrepit
Over a decade later, Perl gets true and false "distinguished booleans" through the new builtin packageDecrepit
D
306

Truth and Falsehood in man perlsyn explains:

The number 0, the strings '0' and "", the empty list "()", and "undef" are all false in a boolean context. All other values are true.

In Perl, the following evaluate to false in conditionals:

0
'0'
undef
''  # Empty scalar
()  # Empty list
('')

The rest are true. There are no barewords for true or false. (Note: Perl v5.38 introduced true and false through the new builtin pragma).

Delaine answered 24/6, 2009 at 4:10 Comment(19)
Is the correct comparison, then, a comparison with zero, as in $var=0 ?Individuality
No. 1. = is not comparison, it's assignment. 2. Do "if ($var) {...}".Ryter
Are you allowed to do the following in Perl? $var = ( $var1 eq $var2 ); This is done all the time in C. How does this work in Perl?Shallop
@BlueWaldo: Yes, that works. $var will (IIRC) be either 0 or 1, in this case.Ryter
@BlueWaldo: you can also use cmp and <=> when comparing and assigning the results of the comparison to a scalar. $var = $var1 cmp $var2; 'cmp' and '<=>' (used for numeric comparisons) returns -1, 0, or 1 if left argument is less than, equal to, or greater than the right argument. Its not boolean but sometimes you may want to know if one argument ir equal or less than or greater than the other instead of just equal or not equal.Venator
@kevinadc: That "sometimes" is usually in the comparator of a sort invocation. :-)Ryter
there aren't any barewords but there is the boolean module on cpan which adds them and can make code more readable imo.Syllabary
Problem 1: An empty list is not false, since it's impossible to check if an list is true or false. An empty list in scalar context returns undef.Ontologism
Problem 2: ('') and '' are the same value. I think you wanted to imply a list with an element that consists of an empty string (even though parens don't create lists), but as I've already mentioned, it's impossible to check if a list is true of false.Ontologism
Problem 3: Objects with an overloaded boolean operator can also be false.Ontologism
@eternicode, Perl does have two specific value it uses when it needs to return true and false, so not only does it have booleans, it has true (!0 aka PL_sv_yes) and false (!1 aka PL_sv_no). Or are you saying Perl should croak whenever something other than these two values are tested for truthness? That would be completely awful. e.g. It would prevent $x ||= $default;Ontologism
It's about time perl had the keywords true and false in it though. It only adds to the confusion when learning perl or switching between languages like I do a lot. I guess there's this search.cpan.org/dist/Keyword-Boolean-0.001/lib/Keyword/… but I'm too lazy to install it. While I'm ranting how about "elseif", "if statement" on a single line without having to have braces and so on!Marseilles
It doesn't need booleans for binary logic ('i.e. one or the other'). Signals are interpolated to be either a logical high or a logical low. @eternicodeViaduct
You missed 0.0 (not "0.0" which is true.) Devel::Peek shows that 0 is SVIV = 0 and 0.0 is SVNV = 0 so they are slightly different values, both false.Carnot
You can install the "boolean" package from CPAN, and then put the following in your code: use boolean qw(true false); You will now have the "barewords" true and false defined.Mercola
@Ontologism $x ||= $default; looks pretty evil to me. It's one of those 'micro-optimizations' which saves 5 seconds of developer time and requires 20 minutes of maintainer time to comprehend.Behistun
@abhi divekar, It's not used an optimization; it's used because it's far simpler and clearer. Consider what happens when you have a multitude of initializations, or if you're in the middle of a larger statement (e.g. f({ foo => $foo // "foo", ... })). And it's positively invaluable when the LHS is complex or has side effects (e.g. f( something_long_or_expensive() // something_else() );). The savings in complexity are incredible. It literally cuts the length of programs by a third. Even if you had to spend 20 minutes once to learn this, it's worth it.Ontologism
@abhidivekar An idiom like $x ||= $default; is extremely useful, and saves a lot of maintainer time once you are familiar with it. It is clear in one glance what is intended, and saves time that would otherwise be spend on understanding confusing nested if statements.Psychoactive
@Ontologism @Psychoactive except that what is usually meant is $x //= $default (give $x a default value if it is undef). $x ||= $default means give $x a default value if its current value is "false", which is something completely different. Unfortunately the defined-or operator was introduced only in 5.10 and some servers still are running 5.8.Upholster
O
77

Since 5.36, you can use true and false from the builtin module/namespace. These are special true and false values that can be identified using is_bool. This is an experimental feature at this time.

But while these could be said to return the true and false, they are are but a true or false value respectively. In fact, every scalar is either true or false.

The most complete, concise definition of a false value I've come across is:

Anything that stringifies to the empty string or the string 0 is false. Everything else is true.

Therefore, the following values are false:

  • The empty string.
  • The string 0.
  • A signed integer with value zero.
  • An unsigned integer with value zero.
  • A floating point number with value positive zero.
  • A floating point number with value negative zero.
  • An undefined value.
  • An object with an overloaded boolean operator that evaluates one of the above.
  • A magical variable that evaluates to one of the above on fetch.

Any other scalar is true.


A note on "true zeroes"

While numbers that stringify to 0 are false, strings that numify to zero aren't necessarily. The only false strings are 0 and the empty string. Any other string, even if it numifies to zero, is true.

The following are strings that are true as a boolean and zero as a number:

  • Without a warning:
    • "0.0"
    • "0E0"
    • "00"
    • "+0"
    • "-0"
    • " 0"
    • "0\n"
    • ".0"
    • "0."
    • "0 but true"
    • "\t00"
    • "\n0e1"
    • "+0.e-9"
  • With a warning:
    • Any string for which Scalar::Util::looks_like_number returns false. (e.g. "abc")
Ontologism answered 13/4, 2011 at 20:53 Comment(9)
if I understood you right the word true in While numbers that stringify to 0 are true should be false or (to prevent confusion) evaluate to false.Barbarian
Your "concise" definition is inconsistent with your longer explanation. Consider: my $value = do { package XXX; use overload q[""] => sub { "XXX" }, q[bool] => sub { 0 }; bless [] };. Now $value will stringify to "XXX" but boolifies to false.Dominus
@tobyink, The concise version isn't perfect, merely the best I've found. It's meant to be practical, not all-encompassing. Do note that value returned by your bool does stringify to 0. Also, you are discouraged from creating inconsistent overloads, and the values you return could be considered such. (e.g. a && can be optimized into a ||, so if these were inconsistent, you'd have a problem.)Ontologism
I'm not sure if 0x00 is covered here.Oversight
@Zaid, Do you mean the value returned by the code 0x00 (the numerical value zero) or the string 0x00 (for which looks_like_number is false)? Either way, it's already covered.Ontologism
@Ontologism so is it standard practice in perl to use 0/1 as boolean values, as in $feature_enabled = 1; ?Highspeed
@Aerovistae, That's probably the most common choice, yes. undef is another common false value, but I'd use 0 for a flag.Ontologism
Can you explain what part of your definition applies to if (() = sub_returning_list) evaluating as true if the sub returns list items, even if they are false?Megganmeggi
@Grinn, A list assignment in scalar context evaluates to the number of scalars to which its RHS evaluates. (See Scalar vs List Assignment Operator for details.) If the sub returns nothing, the assignment will evaluate to 0, which is false. If the sub returns at least one scalar, the assignment will evaluate to a positive number, which is true.Ontologism
P
63

Perl doesn't have a native boolean type, but you can use comparison of integers or strings in order to get the same behavior. Alan's example is a nice way of doing that using comparison of integers. Here's an example

my $boolean = 0;
if ( $boolean ) {
    print "$boolean evaluates to true\n";
} else {
    print "$boolean evaluates to false\n";
}

One thing that I've done in some of my programs is added the same behavior using a constant:

#!/usr/bin/perl

use strict;
use warnings;

use constant false => 0;
use constant true  => 1;

my $val1 = true;
my $val2 = false;

print $val1, " && ", $val2;
if ( $val1 && $val2 ) {
    print " evaluates to true.\n";
} else {
    print " evaluates to false.\n";
}

print $val1, " || ", $val2;
if ( $val1 || $val2 ) {
    print " evaluates to true.\n";
} else {
    print " evaluates to false.\n";
}

The lines marked in "use constant" define a constant named true that always evaluates to 1, and a constant named false that always evaluates by 0. Because of the way that constants are defined in Perl, the following lines of code fails as well:

true = 0;
true = false;

The error message should say something like "Can't modify constant in scalar assignment."

I saw that in one of the comments you asked about comparing strings. You should know that because Perl combines strings and numeric types in scalar variables, you have different syntax for comparing strings and numbers:

my $var1 = "5.0";
my $var2 = "5";

print "using operator eq\n";
if ( $var1 eq $var2 ) {
    print "$var1 and $var2 are equal!\n";
} else {
    print "$var1 and $var2 are not equal!\n";
}

print "using operator ==\n";
if ( $var1 == $var2 ) {
    print "$var1 and $var2 are equal!\n";
} else {
    print "$var1 and $var2 are not equal!\n";
}

The difference between these operators is a very common source of confusion in Perl.

Periphrastic answered 24/6, 2009 at 7:24 Comment(2)
use warnings; instead of #! perl -wBenenson
Using constants as a poor mans macros that way is dangerous. These code examples aren't equivalent: if ($exitstatus) { exit; } vs if ($exitstatus == true) { exit; }, which might not be obvious to a casual observer. (And yes, the last example is poor programming style, but that is beside the point).Routinize
S
16

I recommend use boolean;. You have to install the boolean module from cpan though.

Syllabary answered 3/5, 2010 at 11:16 Comment(2)
In Perl, as in life, there are many truths. The inexperienced like to write silly things like if ($my_true_value == true). Pretending that there is One True Truth is, in my experience, a path to pain, and inefficient code.Triune
Perl is philosophical by natureBoarfish
C
16

My favourites have always been

use constant FALSE => 1==0;
use constant TRUE => not FALSE;

which is completely independent from the internal representation.

Collide answered 8/10, 2015 at 11:0 Comment(1)
Brilliant. You single-handedly fixed the Perl programming language!Muriel
B
9

I came across a tutorial which have a well explaination about What values are true and false in Perl. It state that:

Following scalar values are considered false:

  • undef - the undefined value
  • 0 the number 0, even if you write it as 000 or 0.0
  • '' the empty string.
  • '0' the string that contains a single 0 digit.

All other scalar values, including the following are true:

  • 1 any non-0 number
  • ' ' the string with a space in it
  • '00' two or more 0 characters in a string
  • "0\n" a 0 followed by a newline
  • 'true'
  • 'false' yes, even the string 'false' evaluates to true.

There is another good tutorial which explain about Perl true and false.

Backing answered 13/4, 2015 at 12:56 Comment(0)
Q
7

Beautiful explanation given by bobf for Boolean values : True or False? A Quick Reference Guide

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
Quirita answered 27/11, 2013 at 11:32 Comment(1)
Poor answer, but a strong, reputable source in perlmonks.org. It would be nice to have some real content instead of a comment and a link. :-/Boarfish
S
1

use the following file prefix, this will add to your perl script eTRUE and eFALSE, it will actually be REAL(!) true and false (just like java)

#!/usr/bin/perl
use strict;
use warnings;

use constant { #real true false, compatible with encode_json decode_json for later (we don't want field:false... will be field:0...)
                eTRUE  =>  bless( do{\(my $o = 1)}, 'JSON::PP::Boolean' ),
                eFALSE =>  bless( do{\(my $o = 0)}, 'JSON::PP::Boolean' )
             };

There are, actually, few reasons why you should use that.

My reason is that working with JSON, I've got 0 and 1 as values to keys, but this hack will make sure correct values are kept along your script.

Stringhalt answered 15/1, 2014 at 10:48 Comment(0)
D
1

Perl v5.38 introduced experimental "distinguished booleans" through the new builtin pragma. This means that you now have the true or false that you wanted.

use v5.38;
use experimental qw(builtin);
use builtin qw(true false);

my $var = false;
Decrepit answered 2/11, 2023 at 16:45 Comment(0)
D
-3

Booleans in Raku (the programming language formerly known as Perl_6):

~$ raku
Welcome to 𝐑𝐚𝐤𝐮𝐝𝐨™ v2021.06.
Implementing the 𝐑𝐚𝐤𝐮™ programming language v6.d.
Built on MoarVM version 2021.06.

To exit type 'exit' or '^D'

> my $var = False;
False
> say $var;
False

> say $var.^name
Bool
> say $var.WHAT
(Bool)

> say ++$var
True
> say --$var
False

> say $var.Int
0
> say $var.Int + 1
1
> say ($var.Int + 1).Bool
True
> say $var.Int - 1
-1
> say ($var.Int - 1).Bool
True

> say $var.succ
True
> say $var.Int.succ
1
> say $var.pred
False
> say $var.Int.pred
-1

> say ++($var.Int); #ERROR
Cannot resolve caller prefix:<++>(Int:D); the following candidates
match the type but require mutable arguments:
    (Mu:D $a is rw)
    (Int:D $a is rw --> Int:D)
    #<SNIP>    
> say --($var.Int); #ERROR
Cannot resolve caller prefix:<-->(Int:D); the following candidates
match the type but require mutable arguments:
    (Mu:D $a is rw)
    (Int:D $a is rw --> Int:D)
    #<SNIP>

> exit

https://docs.raku.org/type/Bool
https://docs.raku.org/language/syntax#index-entry-Boolean_(literals)

Dorsy answered 12/9, 2021 at 3:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.