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

Reply via email to