views:

179

answers:

4

When evaluating an expression in a scalar (boolean) context, Perl uses the explicit value 1 as a result if the expression evaluates to true and the empty string if the expression evaluates to false. I'm curious why Perl uses the empty string to represent boolean false value and not 0 which seems more intuitive.

Note that I'm not concerned with Perl treating the empty string as a false in scalar (boolean) context.

+1  A: 

It's not just "" that's false in Perl. As for why... it's either because Perl is awesome or terrible -- depending on your personal preferences :)

thenduks
Perl is the only language which is equally readable before and after RSA encryption.
TBH
@TBH No, APL is. Perl is slightly more readable in unencrypted form.
Chas. Owens
@Chas - I think you meant to say "in encrypted form".
DVK
@DVK Well played sir, well played.
Chas. Owens
+2  A: 

Both number 0 and empty string ultimately evaluate as false in Perl. I think this is a matter of language design. When writing your own code, you can of course assume any which one false encoding convention.

For further details, check out "How do I use boolean variables in Perl?".

jsalonen
+21  A: 

The various logical operators don't return an empty string, they return a false or true value in all three simple scalar types. It just looks like it returns an empty string because print forces a string context on its arguments:

#!/usr/bin/perl

use strict;
use warnings;

use Devel::Peek;

my $t = 5 > 4;
my $f = 5 < 4;

Dump $t;
Dump $f;

Output:

SV = PVNV(0x100802c20) at 0x100827348
  REFCNT = 1
  FLAGS = (PADMY,IOK,NOK,POK,pIOK,pNOK,pPOK)
  IV = 1
  NV = 1
  PV = 0x100201e60 "1"\0
  CUR = 1
  LEN = 16
SV = PVNV(0x100802c40) at 0x100827360
  REFCNT = 1
  FLAGS = (PADMY,IOK,NOK,POK,pIOK,pNOK,pPOK)
  IV = 0
  NV = 0
  PV = 0x100208ca0 ""\0
  CUR = 0
  LEN = 16

For those not familiar with the Perl 5 internals, a PVNV is a scalar structure that holds all three simple scalar types (integer IV, double precision float NV, and string PV). The flags IOK, NOK, and POK mean that the integer, double, and string values are all in sync (for some definition of in sync) so any one of them may be used (i.e. no conversions need to take place if you use it as an integer, double, or string).

I assume the empty string was chosen for the false string because it is smaller and is more in keeping with the idea of a false string than "0". Ignore my statement about it being smaller, both "" and "1" are the same size: sixteen characters. It says so right in the dump. Perl 5 adds extra space to strings to allow them to grow quickly.

Oh, and I hate you. In researching this I have found that I have lied in perlopquick and will now have to find a way to fix it. If only you had been like all of the other sheep and just accepted Perl 5's surface weirdness as fact, I would have less work to do.

Chas. Owens
I hate/love both of you -- this question caused me to send a docpatch to p5p just now: perlguts mistakenly refers to `PL_sv_no` (the "false" scalar in question) as `PL_sv_false`. :)
hobbs
@Piotr Dobrogost See what you have done! See what comes from asking questions? You are making things in Perl 5 better! How can you live with yourself?
Chas. Owens
Thanks, applied, hobbs. :-)
rafl
@hobbs Could you care to elaborate?
Piotr Dobrogost
@Piotr Dobrogost The [`perldoc perlguts`](http://perldoc.perl.org/perlguts.html) document incorrectly stated that there was a `PL_sv_false` C function that returned the same value as `1 < 0`. The function is really named `PL_sv_no`. Read the [p5p post](http://www.nntp.perl.org/group/perl.perl5.porters/2010/10/msg164959.html) for more information.
Chas. Owens
+3  A: 

You can overload the stringification of true, false and undef, like this:

&Internals::SvREADONLY( \ !!1, 0);    # make !!1 writable
${ \ !!1 } = 'true';                  # change the string value of true
&Internals::SvREADONLY( \ !!1, 1);    # make !!1 readonly again
print 42 == (6*7);                    # prints 'true'

&Internals::SvREADONLY( \ !!0, 0);    # make !!0 writable
${ \ !!0 } = 'false';                 # change the string value of false
&Internals::SvREADONLY( \ !!0, 1);    # make !!0 readonly again
print 42 == (6*6);                    # prints 'false'
MkV
Very nice customization. I had no idea Perl allows for such a thing.
Piotr Dobrogost
So very wrong. +1.
rafl
The `Internals` package and functions or variables in it are not for public consumption (hence the name). Globally changing the value of the true and false values returned by operators is inadvisable in the extreme. Circumventing `SvREADONLY`'s prototype is just icing on the cake. That said, nifty.
Chas. Owens