Day 19 – False truth

Today’s advent gift teaches us how to use mixins for nefarious and confusing purposes. In fact, this feature will probably appear partly insane, but it turns out to be quite useful. Enter the but operator:

my $value = 42 but role { method Bool  { False } };
say $value;    # 42
say ?$value;   # False

So you see, we overload the .Bool method on our $value. It doesn’t affect other integers in the program, not even other 42s in the program, just this one. Normally, for Ints, the .Bool method (and therefore the prefix:<?> operator) returns whether the number is non-zero, but here we make it always return False.

In fact, there’s a shorter way to write this for enum values, of which False is one.

my $value = 42 but False;

Since False is a value of the Bool type, it will automatically overload the .Bool method, which by convention is a kind of conversion method in Perl 6. Values of other types will of course overload their corresponding conversion method.

Here’s the part that turns out to be quite useful: in Perl 5 when you put a &system call in an if statement wanting to check for success, you have to remember to negate the result of the call, since in bash only zero means success:

if ( system($cmd) == 0 ) {  # alternatively, !system($cmd) 
    # ...
}

But in Perl 6, the corresponding &run routine returns the above kind of overloaded integers; these boolify to True if and only if the return value is zero, which is the opposite of the default Int behavior, and just what we need.

if run($cmd) {  # we don't negate
    # ...
}

Oh, and here’s the part that appears insane. :-) We can overload the .Bool method of boolean values!

my $value = True but False;
say $value;    # True
say ?$value;   # False

Yes, Perl 6 allows you to shoot yourself in the foot in this particular way. Though I don’t see why anyone would want to do this except for obfuscatory purposes, I’m kinda glad Perl 6 has the presence of mind to keep track of the subtleties of that type of overloading. I know I almost don’t. :-)