27

In reading about Perl 6, I see a feature being trumpeted about, where you no longer have to do:

return "0 but true";

...but can instead do:

return 0 but True;

If that's the case, how does truth work in Perl 6? In Perl 5, it was pretty simple: 0, "", and undef are false, everything else is true.

What are the rules in Perl 6 when it comes to boolean context?

jjmerelo
  • 22,578
  • 8
  • 40
  • 86
raldi
  • 21,344
  • 33
  • 76
  • 86

6 Answers6

18

Perl 6 evaluates truth now by asking the object a question instead of looking at its value. The value is not the object. It's something I've liked about other object languages and will be glad to have in Perl: I get to decide how the object responds and can mutate that. As ysth said, you could do that in Perl 5 with overload, but I always feel like I have to wash my hands after doing it that way. :)

If you don't do anything to change that, Perl 6 behaves in the same way as Perl 5 so you get the least amount of surprise.

Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
brian d foy
  • 129,424
  • 31
  • 207
  • 592
  • 1
    That'd be more object oriented than Ruby - only `false` and `nil` lack truthiness, and there's nothing you can do about it, unless you monkeypatch `!` and do `!!foo`. – Andrew Grimm Dec 09 '11 at 06:01
11

See Synopsis 12: Roles.

The rules are the same, but the "but" copies the 0 and applies a role to the copy that causes it to be true in boolean context.

You can do the same thing with overload in Perl 5.

brian d foy
  • 129,424
  • 31
  • 207
  • 592
ysth
  • 96,171
  • 6
  • 121
  • 214
11

Truthness test just calls the .true method on an object, so the "mix in" operation $stuff but True just (among other things) overrides that method.

This is specified in S02, generally enum types (of which Bool is one) are described in S12.

moritz
  • 12,710
  • 1
  • 41
  • 63
6

According to O'Reilly's Perl 6 and Parrot Essentials, false is 0, undef, the empty string, and values flagged as false. true is everything else.

Also, Perl 6 has both 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).

See http://www.mail-archive.com/macosx@perl.org/msg09930.html

brian d foy
  • 129,424
  • 31
  • 207
  • 592
Mark Cidade
  • 98,437
  • 31
  • 224
  • 236
3

So to combine what I think to be the best of everyone's answers:

When you evaluate a variable in boolean context, its .true() method gets called. The default .true() method used by an object does a Perl 5-style <0, "", undef> check of the object's value, but when you say "but True" or "but False", this method is overridden with one that doesn't look at the value just returns a constant.

One could conceivable write a true() method which, say, returned true when the value was even and false when it was odd.

brian d foy
  • 129,424
  • 31
  • 207
  • 592
raldi
  • 21,344
  • 33
  • 76
  • 86
1

One false value that gets neglected nearly everywhere is "0". I recently made this painful discovery that "0" is false in PERL 5. Gee. A non-empty string that's false. I was really hoping that would change in PERL6, but I guess not.

> if ( "0" ) { say "True" } else { say "False" }
False

The ||= idiom clobbered some strings I really wasn't expecting:

$ perl -e '$x = "0"; $x ||= ""; print ">>$x<<\n";'
>><<
kovacsbv
  • 351
  • 4
  • 11
  • That is why [defined-or](http://perltraining.com.au/tips/2008-03-03.html) `//` is so nice. It's enabled (starting in Perl 5.10) by `use 5.010`. – Christopher Bottoms May 15 '15 at 16:06
  • Oops, I just remembered that since defined-or did not conflict with previous syntax, it is enabled by default. – Christopher Bottoms May 15 '15 at 22:22
  • 1
    This answer was written about P6 prior to its first official release in 2015. `if ( "0" ) { say "True" } else { say "False" }` yields `True`. The P6 compiler rejects the other line at compile-time. With two changes it compiles and produces what I assume @kovacsbv would consider the correct result: `my $x = "0"; $x ||= ""; print ">>$x\<<\n"; # >>0<<`. – raiph May 16 '19 at 16:10