Background and Initial Questions
I'm excited to see such great advances in Rakudo and have enjoyed its
fundamental power and beauty. In reading Tim Bunce's blog, I saw a
call for an introduction to Perl 6 for Java programmers. Since Java
programming is a big part of my day job, I decided to see where I could
get with that guide.
Now I have questions and one apparent problem, though I hope that is with
me and not with Rakudo or Perl 6. In addition to my questions, I welcome
any input regarding style, naming conventions, etc. I want to write the
best Perl 6 for my guide.
Allow me an understatement: Java is Object Oriented. So, I think a guide
for the Java inclined should begin with classes. Here is my first class:
class Die;
has Int $!sides;
method new( Int $sides = 6 ) {
return self.bless( *, :$sides );
}
method roll() returns Int {
return round 1 + rand * $!sides;
}
I copied the idea for this from the excellent beginner's guide PDF in the
Rakudo star distributions. Here is my first question: What exactly are
the arguments of bless? In particular, what does the asterisk mean and
do I have other choices for it? Further, why does the sides attribute
need a leading colon (or does it)?
Problems with Default Arguments in Aggregating Constructors
Having made a single Die with my previous example, I set out to make
a pair of dice as would be needed for a game like Backgammon, Monopoly, etc.
This class aggregates two Die objects and rolls them in simulation:
use Die;
class Die-Pair;
has Die $!die1;
has Die $!die2;
has Int $!total = 0;
has Bool $.was-doubles;
method new( Int $sides1?, Int $sides2? ) {
my Die $die1 = Die.new( sides => $sides1 );
my Die $die2 = Die.new( sides => $sides2 );
return self.bless( *, :$die1, :$die2 );
}
method roll() returns Int {
my Int $roll1 = $!die1.roll();
my Int $roll2 = $!die2.roll();
$!total = $roll1 + $roll2;
$!was-doubles = ( $roll1 == $roll2 );
return $!total;
}
my Die-Pair $die-pair = Die-Pair.new( 6, 6 );
for 0..12 -> $i {
my $roll = $die-pair.roll();
my $was-doubles = $die-pair.was-doubles();
say "$i Roll! $roll was doubles? $was-doubles";
}
This works fine as is. I have only one question here: Why do I need
to change from $.was-doubles to $!was-doubles when I access the attribute
in instance methods? When I tried to use $.was-doubles, the compiler
threw: Cannot modify readonly value. I'm assuming this is the correct
behavior, but I'd like a bit of clarification.
Finally, I've come to my problem. Recall that the Die class provides
a default number of six sides. Suppose I replace the Die-Pair
constructor call with this:
my Die-Pair $die-pair = Die-Pair.new();
I want to receive the default from the Die constructor for each instance
I construct. But the output tells me this did not work:
0 Roll! 2 was doubles? 1
1 Roll! 2 was doubles? 1
2 Roll! 2 was doubles? 1
3 Roll! 2 was doubles? 1
...
What must I do so that my aggregating class can allow the caller to
use the defaults of the aggregated class? My current work around is
to use multi constructors:
multi method new( Int $sides1, Int $sides2 ) {
my Die $die1 = Die.new( $sides1 );
my Die $die2 = Die.new( $sides2 );
return self.bless( *, :$die1, :$die2 );
}
multi method new() {
my Die $die1 = Die.new();
my Die $die2 = Die.new();
return self.bless( *, :$die1, :$die2 );
}
This is what I would need to do in Java. But, I wanted to make the point
that defaults could eliminate the need for this type of overloaded
constructor
in Perl 6.
Thanks for reading,
Phil