Perl6
An Object
class Test {
method baz {
say "hi";
}
}
my $obj = Test.new;
$obj.baz();
Constructors
Unfortunately, the
Constructors
page in the
Perl6
Object Oriented Cookbook is broken. From what I can read in
Synopsis
12:
You can write your own BUILD submethod to control initialization. If
you name an attribute as a parameter, that attribute is initialized
directly, so
submethod BUILD ($.tail, $:legs) {}
is equivalent to
submethod BUILD ($tail, $legs) {
$.tail = $tail;
$:legs = $legs;
}
Only problem is that Pugs doesn't seem to like BUILD. This code:
class Test {
submethod BUILD ($.word) {}
method baz {
say $.word;
}
}
my $obj = Test.new("hi");
$obj.baz;
Tells me:
*** Can't use positionals in default new constructor
at ./test2.p6 line 11, column 12-27
Okay, I think. I'll use a key. Digging through my memory of the
p6l mailing list, I try:
class Test {
submethod BUILD ($.word) {}
method baz {
say $.word;
}
}
my $obj = Test.new(:word("hi"));
$obj.baz;
It works! But now on a hunch, I try:
class Test {
method baz {
say $.word;
}
}
my $obj = Test.new(:word("hi"));
$obj.baz;
Huh. Still works. Okay, now's not the time for questions, so I'll call
this good and move on!
Update: I found the following which clarifies: "All classes inherit a default new constructor from Object. It expects all arguments to be named parameters initializing attributes of the same name."
There Goes the Neighborhood
Some favorite features of Perl6:
my $foo;
my $baz = 1;
$foo //= 2;
$baz //= 2;
say $foo;
say $baz;
my $x = 4;
if 2 < $x < 5 { say 'hi'; }
The Mystery of the Missing Defaults
From reading the various Perl6 docs, I get the sense that this should work:
class Test {
has $.foo = 3;
}
my $obj = Test.new;
say $obj.foo;
But it doesn't.
***
unexpected "{"
expecting trait, ";" or end of input
at ./test4.p6 line 3, column 12
I've also seen references to something like this:
class Test {
has $.foo is :default(3);
}
my $obj = Test.new;
say $obj.foo;
But no dice there either.
Update: I just found a
test
for this in the repository. I'm going to see if it works. Pasting
class Foo2 { has $.bar = "baz"; } into Pugs sure doesn't work.
Heh Heh... You Said MONKEY BUT!
I don't really know why this is called the "
monkey but", but
that's what Damian called it in his Perl6 talk at OSCON. It's pretty
cool though.
sub ($sth) {
$sth->execute();
return $sth->fetch_row() but {
$sth->finish();
};
}
I'm a little frustrated by the required ';' after the block. =\
Do Be Do Be Do!
Unlike Perl5, the contents of { } blocks are not evaluated. Instead,
in Perl6, { 4 + 5 } defines an anonymous subroutine. I believe the
symantics are identical to sub { 4 + 5 }, which is also a supported
form in Perl6.
In order to get code evaluated in a new context, you know use a "do".
my $foo = do { 4 + 5 };
What for?
I still remember the look in a certain C programmer's eyes when I
introduced him to Perl5's 'foreach' loop. I've since been won over by
collection closure methods (iteration methods that take functions as
parameters, ala Smalltalk or Ruby's blocks). But the 'foreach' loop is
still good stuff.
In Perl6, 'foreach' is spelled 'for'. And it looks a little different.
my @array = (1, 2, 3);
for @array -> $item {
say $item;
}
Perl5 programmers might be freaking out here. I remember thinking, uh,
that's different. Yup.
Okay, digression time. So far we've seen that you can declare
anonymous subs these to ways:
my $anon_sub1 = sub ($word) { say $word };
my $anon_sub2 = { say "I don't think this form can have parameters" };
Well, there's another way. They're called "pointy subs". These
vampiric functions look a little like this...
my $sub_three = -> $word { say $word };
Yeah, okay, that looks a little weird, but now think about it in the
context of that for loop.
my @array = (1, 2, 3);
for @array -> $item {
say $item;
}
The Perl6 for loop is a collection closure function. Whoa. Good
stuff. Unfortunately, pugs is a little picky about for loops. Let's
digress.
Here's a function that takes a parameter and a function as parameters,
then calls the function with the parameter. Below it are some ways to
invoke it.
sub doit ($param, $func) {
$func($param);
}
my $sayit = sub ($word) { say $word };
doit("badger", $sayit);
doit("badger", sub ($word) { say $word });
doit("badger", { say $_ });
doit("badger", &say);
The first three invokations work, the last one is a no go, though I'm
not really sure why. It seems to me that should pass it the "say"
function we've been using all along, but there must be some
weirdness. Anyways, the second and third invokation have that horrible
});. Ladies and gentlemen, I heard it from Matz's
mouth.
}); makes Matz sad. And you wouldn't want to make the
Matz sad, would you? That's why he created this special syntax for
passing a single block. And it's a really good syntax (warning! Ruby
code ahead!):
obj.meth(param) {
we.are(in, a, codeblock, now)
}
Of course, every once in a while this really pisses me off, because
what if I want to pass two code blocks? Well, the shit hits the fan
and you have to change syntax to pass the other one, and they have to
be handled differently on the receiving end. Ugh.
Seems like Perl6 has a pretty good answer for this, and it's "pointy
subs". What's that you say?
doit("badger", -> $word { say $word });
Hardly looks better? Well, you're right. But how about this:
doit "badger" -> $word { say $word };
doit "badger" -> $word {
say $word;
}
Looks pretty good, eh? Only problem is: it doesn't work in pugs
yet. That said, I think this is great, because not only is it a nice
short lambda syntax, the arrow suggests a flowing forward that makes
passing multiple anonymous functions into another function look pretty
logical.
But I Want RUBY!
Me too man, me too. But I also really want Perl6. So have a look at
this official and very real Perl6 code:
my @list = (1, 2, 3);
say @list.map:{ $_ + 1 };
I'm not even kidding! Bam! Now, the question remains, will Perl6 have
all the wonderful methods we've come to know and love in the Ruby Core
classes? I sure hope so, and I might even be willing to write some
code if I have to (to make sure). But thankfully, this stuff can be
added 3rd party pretty easily.