Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What do Perl functions that return Boolean actually return

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?

like image 542
Anon Gordon Avatar asked Nov 22 '12 21:11

Anon Gordon


3 Answers

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';
like image 58
ikegami Avatar answered Nov 15 '22 13:11

ikegami


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,"").)

like image 20
ysth Avatar answered Nov 15 '22 14:11

ysth


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

like image 3
Moritz Bunkus Avatar answered Nov 15 '22 14:11

Moritz Bunkus