What do Perl functions that return Boolean actually return
Asked Answered
E

4

12

The Perl defined function (and many others) returns "a Boolean value".

Given Perl doesn't actually have a Boolean type (and uses values like 1 for true, and 0 or undef for false) does the Perl language specify exactly what is returned for a Boolean values? For example, would defined(undef) return 0 or undef, and is it subject to change?

Evolutionary answered 22/11, 2012 at 21:33 Comment(1)
Sidenote: you can turn any value into its corresponding boolean with double negation. This leads to the !! pseudo-operator. Very useful for returning the generic truthy or falsey value instead of some magic number.Brassie
L
12

In almost all cases (i.e. unless there's a reason to do otherwise), Perl returns one of two statically allocated scalars: &PL_sv_yes (for true) and &PL_sv_no (for false). This is them in detail:

>perl -MDevel::Peek -e"Dump 1==1"
SV = PVNV(0x749be4) at 0x3180b8
  REFCNT = 2147483644
  FLAGS = (PADTMP,IOK,NOK,POK,READONLY,pIOK,pNOK,pPOK)
  IV = 1
  NV = 1
  PV = 0x742dfc "1"\0
  CUR = 1
  LEN = 12

>perl -MDevel::Peek -e"Dump 1==0"
SV = PVNV(0x7e9bcc) at 0x4980a8
  REFCNT = 2147483647
  FLAGS = (PADTMP,IOK,NOK,POK,READONLY,pIOK,pNOK,pPOK)
  IV = 0
  NV = 0
  PV = 0x7e3f0c ""\0
  CUR = 0
  LEN = 12

yes is a triple var (IOK, NOK and POK). It contains a signed integer (IV) equal to 1, a floating point number (NV) equal to 1, and a string (PV) equal to 1.

no is also a triple var (IOK, NOK and POK). It contains a signed integer (IV) equal to 0, a floating point number (NV) equal to 0, and an empty string (PV). This means it stringifies to the empty string, and it numifies to 0. It is neither equivalent to an empty string

>perl -wE"say 0+(1==0);"
0

>perl -wE"say 0+'';"
Argument "" isn't numeric in addition (+) at -e line 1.
0

nor to 0

>perl -wE"say ''.(1==0);"


>perl -wE"say ''.0;"
0

There's no guarantee that this will always remain the case. And there's no reason to rely on this. If you need specific values, you can use something like

my $formatted = $result ? '1' : '0';
Ludvig answered 22/11, 2012 at 22:0 Comment(3)
ikegami you might consider adding a link to this answer for more information :)Embrasure
The special false value is documented in perlsyn. While that's not precisely a guarantee it'll never change, Perl 5 doesn't break backwards compatibility without a very good reason.Magic
@cjm, Aj cool, I didn't know it was documented. That does make it quite safe.Ludvig
P
5

They return a special false value that is "" in string context but 0 in numeric context (without a non-numeric warning). The true value isn't so special, since it's 1 in either context. defined() does not return undef.

(You can create similar values yourself with e.g. Scalar::Util::dualvar(0,"").)

Procreant answered 22/11, 2012 at 21:48 Comment(0)
W
3

Since that's the official man page I'd say that its exact return value is not specified. If the Perl documentation talks about a Boolean value then then it almost always talks about evaluating said value in a Boolean context: if (defined ...) or print while <> etc. In such contexts several values evaluate to a false: 0, undef, "" (empty strings), even strings equalling "0".

All other values evaluate to true in a Boolean context, including the infamous example "0 but true".

As the documentation is that vague I would not ever rely on defined() returning any specific value for the undefined case. However, you'll always be OK if you simply use defined() in a Boolean context without comparing it to a specific value.

OK: print "yes\n" if defined($var)

Not portable/future proof: print "yes\n" if defined($var) eq '' or something similar

Wrinkly answered 22/11, 2012 at 21:48 Comment(0)
A
3

It probably won't ever change, but perl does not specify the exact boolean value that defined(...) returns.

When using Boolean values good code should not depend on the actual value used for true and false.

Example:

# not so great code:
my $bool = 0;   #
...
if (some condition) {
  $bool = 1;
}

if ($bool == 1) { ... }

# better code:
my $bool;       # default value is undef which is false

$bool = some condition;

if ($bool) { ... }

99.9% of the time there is no reason to care about the value used for the boolean. That said, there are some cases when it is better to use an explicit 0 or 1 instead of the boolean-ness of a value. Example:

sub foo {
    my $object = shift;
    ...
    my $bool = $object;
    ...
    return $bool;
}

the intent being that foo() is called with either a reference or undef and should return false if $object is not defined. The problem is that if $object is defined foo() will return the object itself and thus create another reference to the object, and this may interfere with its garbage collection. So here it would be better to use an explicit boolean value here, i.e.:

  my $bool = $object ? 1 : 0;

So be careful about using a reference itself to represent its truthiness (i.e. its defined-ness) because of the potential for creating unwanted references to the reference.

Attitudinize answered 22/11, 2012 at 21:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.