In a message dated Mon, 15 Oct 2007, Doug McNutt writes:
At 18:20 -0700 10/15/07, Michael Barto wrote:
I think in the more newer languages, they have implemented true booleans. Perl
is kind of old school.
use constant TRUE => 1;
use constant FALSE => 0;
Is a complete solution in perl 5.
Um, no, it's not:
#!/usr/bin/perl
use strict;
use warnings;
use constant TRUE => 1;
use constant FALSE => 0;
# Return a list of the sequence of even numbers from 0..$num
# or false if we got an odd number
sub evens_up_to {
my $num = shift;
if ($num % 2) {
# didn't get an even!
return FALSE;
}
return grep { not $_ % 2 } 0..$num;
}
for my $n (2, 4, 5) {
if (my @nums = evens_up_to($n)) {
print "$n is even: @nums\n";
}
else {
print "$n is not even.\n";
}
}
Output is:
2 is even: 0 2
4 is even: 0 2 4
5 is even: 0
Oops. Now, change the return line:
--- true.pl 2007-10-17 12:26:28.000000000 -0400
+++ truenew.pl 2007-10-17 12:27:20.000000000 -0400
@@ -13,5 +13,5 @@
if ($num % 2) {
# didn't get an even!
- return FALSE;
+ return; # false via bare return
}
Now you get:
2 is even: 0 2
4 is even: 0 2 4
5 is not even.
Without resorting to tied handles or objects or other heavyweight
chicanery, there is no single "FALSE" value you can define that will be
false in all cases. Better to use bare return when it may be used like
the above.
On the other hand, when a subroutine returns a scalar boolean, you
probably *do* want to return 0 or undef, otherwise you can get into this
nasty situation:
my ($ready1, $ready2) = ($data1->is_ready, $data2->is_ready);
If is_ready() uses bare "return" fore false, then in the case where $data1
is not ready but $data2 is, $ready1 would be set to 1 and $ready2 would be
undef, the exact opposite of what you'd expect, because $data1->is_ready
would return the empty list so $data2->is_ready would squeeze over and
fill the $ready1 spot. Nasty.
Moral of the story: there is no single false value in Perl 5, and trying
to pretend there is one that is valid in all situations is asking for
trouble.
As others have already noted, Perl 6 fixes this by both having a primitive
boolean type and by having True and False roles that any value can mix in
(so you can have a "0 but True" value or a "1 but False" one for example,
or a false list containing elements, or a true list that's empty).
Trey