Perl 6 : Not Just For Damians
by Piers Cawley
|
Pages: 1, 2, 3, 4
All operators get 'proper' function names.
This one almost had me punching the air. It's brilliant. Especially if, like me, you're the kind of person who goes slinging function references around. (One of the things that I really like about Ruby is its heady mix of functional style higher order functions and hard core object orientation. It looks like Perl's getting this too.)
Again, time to make with the examples. Consider the following perl code from an Assertion package (this is in Perl 6, it's too hard to write clearly in Perl 5).
&assert_with_comparator := {
unless ($^comparator.($^a, $^b)) {
throw Exception::FailedComparison :
comparator => $^comparator,
result => $^a,
target => $^b
}
}
&assert_string_equals := assert_with_comparator(&operator:eq);
&assert_num_equals := assert_with_comparator(&operator:==);
&assert_greater_than := assert_with_comparator(&operator:>);
That's full strength Perl 6 that is, complete with currying, operators
as functions, := binding, : used to disambiguate indirect object
syntax, the whole nine yards. And it is still obviously a Perl
program. The intent of the code is clear, even without comments, and
it took very little time to write. Of course, I am assuming an
Exception class, but we've already got that in Perl 5; take a look at
the lovely Error.pm.
I'm not going to rewrite assert_with_comparator, but just look at
the Perl 5 version of the last line of that example:
*Assert::assert_greater_than =
$assert_with_comparator->(sub { $_[0] > $_[1] });
Don't try and tell me that the intent is clearer in Perl 5 than in Perl 6, because I'll be forced to laugh at you.
binary and unary '.'
I confess that I'm still not sure I see where binary '.' is a win over
'->', especially given that Larry has mandated that most of the time
you won't even need it.
Unary '.' is looking really cool. If I read the Apocalypse right, this
means that, instead of writing object methods like:
sub method {
my $self = shift;
...
$self->{attribute} = $self->other_method(...);
...
}
We can write:
sub method {
...
$.attribute = .other_method(...);
...
}
Which is, once more clean, clear and perl like. This is the kind of
notation I want Right Now. And, frankly, it'd just look silly if you
replaced those '.'s with '->' (and should one parse
$->attribute as an instance variable accessor, or as $- >
attribute). Okay, I'm convinced. Replace '->' with '.' already.
Explicit stringification and numification operators
Again, these have got to be good magic, especially with the NaN stuff
(though that's been the cause of some serious debate on perl6-language
and may not be the eventual name). In at least one of the modules I'm
involved in writing and maintaining, this would have been so useful:
# geq: Generic equals
sub operator:geq is prec(\&operator:eq($$)) ($expected, $got)
{
# Use numericness of $expected to determine which test to use
if ( +$expected eq 'NaN') { return $expected eq $got }
else { return $expected == $got }
}
sub assert_equals ($expected, $got; $comment)
{
$comment //= "Expected $expected, got $got";
$expected geq $got or die $comment;
}
Hey! That looks just like Perl! (Except that, to do the same thing in Perl 5, you have to jump through some splendidly non-obvious hoops. Trust me, I've done that.)
:=
This one had me scratching my head as I read the Apocalypse. On
reading the Exegesis, things become a good deal clearer. := looks like
it's going to be an easy way to export symbols from a module, now that
typeglobs have gone away:
package Foo;
sub import ($class, @args) {
# This is an example, ignore the args
&{"${class}::foo"} := &Foo::foo;
}
Of course, this isn't the only place where := will be used. Thankfully
we'll be able to use it almost everywhere without having to remember
all the caveats that used to surround assigning to typeglobs. Here's
another example in Perl 6 of something that would be impossible in
Perl 5:
$Sunnydale{ScoobyGang}{Willow}{Traits} = [qw/cute geeky/];
# Oooh Seasons 4 and 5 happened and I want
# to use a trait object now
$traits := $Sunnydale{ScoobyGang}{Willow}{Traits};
$traits = new TraitCollection: qw/sexy witch lesbian geek/;
Nothing special there you say. Well, yes, but let's take a look at
print $Sunnydale{ScoobyGang}{Willow}{Traits}
# sexy witch lesbian geek
# Or however a TraitCollection stringifies.
You can almost do this in Perl 5, but only if you continue to use an array:
local *traits = $Sunnydale{ScoobyGang}{Willow}{Traits};
@traits = qw/sexy witch lesbian geek/;
If you want to switch to using a TraitCollection, you'll have to go
back and use the full specifier.
I think this is another of those bits of syntax that I'd like now, please.
Binary :
This is going to make life so much easier for the parser if nothing else. Right now, indirect object syntax can be very useful. However, if you've ever tried to use it in anger, well, you've ended up using it in anger because there are some subtle gotchas that will catch you out. Binary : lets us disambiguate many of these cases and helps to reclaim indirect object syntax as a useful way of working.
And so on... What's not to like? The sugar is sweet, the consistency is just right, and the old annoyances are going away.

