develooper Front page | perl.perl5.porters | Postings from June 2003

perlbool.pod rev.2

Thread Previous | Thread Next
From:
Dan Kogai
Date:
June 30, 2003 04:35
Subject:
perlbool.pod rev.2
Message ID:
D93B74F4-AAEE-11D7-9F5D-000393AE4244@dan.co.jp
Autrijus and Rafael,

Here it is, the 2nd rev.

"0 but Dan the Perl5 Porter"

=head1 NAME

perlbool - semantics of boolean operations and conversions in Perl

=head1 SYNOPSIS

   $f = "0";          # false by definition
   $f = "";           # false by definition
   $f = 0;            # false by definition
   $f = 0.00;         # false because 0.00 == 0.
   $t =  \$a;         # always true
   $f = undef         # always false
   $t = 1;            # true
   $f = 10 - 10;      # equals 0 so false
   $t = "0.00";       # true! see below
   $f = "0.00" + 0    # numerically 0 so false
   $t = "0 but true"; # true, though 0 in numeric conversion
   @f = ();           # scalar @f is 0 so false
   @t = (0);          # scalar @t is 1 so true!
   %h = (0 => undef); # scalar %h is nonzero so %h is true
   delete $h{0};      # scalar %h is now 0 so %h is false

=head1 DESCRIPTION

This document describes how Perl distinguish between true and false.

To perl, only the following values are false and everything else is
true.

=over

=item *

string C<""> (null string) and C<"0">

=item *

number C<0>

=back

Consider the above as axioms and any other "theorems" are reduced to
the axioms above.

=over

=item *

All references are true since it is neither string nor number.
This is unlike C which has null pointers.

=item *

When boolean values are needed, perl does not do any type coercion.
It just checks to see if the value matches  C<"">, C<"0">, or C<0>.

That is why C<"0.00"> is true while C<"0.00"+0> is false.  Though
"0.00" is numerically 0, it is "0.00" until numerical value is needed,
which is neither "" nor "0".

=back

=head2 References

Unlike C which has null pointers, perl's reference is always true
because in string context it would be something like
C<SCALAR(0x8134654)> in string and C<135480916> in numerical context
(because C<0x8134654> is hexadecimal for C<135480916>).

In practice perl does not waste time coercing references to strings
just to see if it is true because perl already knows this theorem

=head2 undef

C<undef()> is always false because it would evaluate to C<""> in
string context and C<0> in numerical context.

Like references, perl already knows C<undef()> is always false so
no coercion takes place.

=head2 Boolean values of arrays and hashes

For boolean values of arrays and hashes, perl just uses C<scalar()>
thereof.  In other words, boolean values of arrays and hashes are
false when and only when they are empty.

C<@a = ()> is false but C<@a = (0)> and C<@a = ("")> are both true.

=head1 0 but true

Like C, many functions in perl returns 0 on failures so you can write
C<if (func()){....}> instead of C<if (function() == 0){....}>.  But
sometimes you want 0 to be a valid, successful numerical value.  For
such cases, use C<0 but true> on success and C<undef> on failure.

As a matter of fact, perl's built-in C<ioctl()>, C<semget()> and
C<sysseek()> uses this semantics so you can safely say

   $offset = sysseek($fh 0, SEEK_CUR)
     or die "sysseek failed: $!";

Instead of lengthy

   defined($offset = sysseek($fh 0, SEEK_CUR))
     or die "sysseek failed: $!";

Of couse C<0 but true> is not the only valid solution.  C<0e0>, C<0.0>
or even C<0.> is okay (L<Net::POP3>, for instance, uses C<0E0>).

However, it is good to remember that C<0 but true> is the one used by
perl built-in functions.  It is also the most self-explanatory.

=head1 Boolean Context vs. Boolean Value

Though perl does not have explicit boolean value like C<t> or C<nil> in
LISP and ruby, perl does have boolean context.

   $a;         # void context
   $a+1        # scalar context
   push @a, $a # array context
   if ($a)     # boolean context

What is interesting is that perl's comparison operators return values
in scalar context; C<1> for true and C<undef> for false.

   not($a)+1;  # 1 if $a is true and 2 otherwise.

The lack of boolean value is no problem since boolean context exists.
See L</Overload> for such cases that boolean context does differ from
scalar context.

=head1 Overload

Because perl does have boolean context, you can use L<overload> to
give your object a different idea from perl on what is true and false.
The following example make a scalar which is always false.

   package NeverTrue;
   use overload
     'bool'   => sub { 0 },
     '""'     => sub { my $self = shift; $$self },
     '0+'     => sub { my $self = shift; $$self },
     fallback => 1;
   sub new {
     my $class = ref $_[0] ? ref shift : shift;
     my $value = shift;
     return bless \$value => $class;
   };

   package main;
   my $t = NeverTrue->new("1 but false");
   printf "Boolean: %s\n", $t ? 't' : 'f';
   printf "String:  %s\n", $t . "";
   printf "Number:  %d\n", $t + 0;

=head1 AUTHOR

0th draft by Dan Kogai <dankogai@dan.co.jp>

Revision by Tassilo von Parseval <tassilo.parseval@post.rwth-aachen.de>,
Autrijus Tang <autrijus@autrijus.org>,
Rafael Garcia-Suarez <raphel.garcia-suarez@hexaflux.com>,
and Perl5 Porters <perl5-porters@perl.org>


=head1 SEE ALSO

L<perldata>, L<perlop>, L<perlsyn>, L<perlnumber>, L<overload>

pp. 29-30 of "Programming Perl", 3rd Ed.
L<http://www.oreilly.com/catalog/pperl3/>


Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About