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:

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. :-)

Like this:

LikeLoading...

Related

This entry was posted on December 19, 2010 at 12:00 am and is filed under 2010. You can follow any responses to this entry through the RSS 2.0 feed.
You can leave a response, or trackback from your own site.

7 Responses to “Day 19 – False truth”

I’m confused on one issue. You say “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.”

Does it ALWAYS return False? If so, how does the overloaded &run work? How do you specify the conditions on when it returns True and when it returns False? Specifying when something returns True or False is a very useful feature. Having it ALWAYS return one specific value would be much less so, since there would be no need to every check it’s return value.

Regardless of the object’s type, when you write prefix:<?>, that gets translated into .Bool. You’re absolutely right that the .Bool method on the Bool type doesn’t do much; it basically looks like this:

method Bool { self }

In other words, a kind of identity operation.

As to why there’d be a need to call the .Bool method on something that’s already Bool (besides the trivial reason that it’s always done): there’s not really any good reason to do that… until someone overrides the method, as in this post. An optimizer that could prove that no overriding has taken place would be free to remove the call.