Perl6 metaprogramming update
This post is an update to my Anyone for Perl 6 metaprogramming? article and gist using Rakudo Star (October 2010 release).
Now I expected one change to the code and one optional improvement that I could now make. However along with these I got two extra enforced changes.
Re-opening a class
First the expected change to re-opening a class:
class Ninja is also { ... }
# is now...
augment class Ninja { ... }
However for this to work I needed to add the following:
use MONKEY_TYPING;
A pragmatic addition. If you’re gonna shoot yourself in the foot then at least you have to prepare for it in advance
NB. Rakudo nicely gave me a fatal warning when I tried to re-open the class and politely told me that use MONKEY_TYPING was needed it I wanted to augment class Ninja.
Applying a role to an object (instance)
Now the next change was optional but it was a more succinct way to add a role to an object. Previously I had to create a role and then apply it to object:
role ThrowStar {
method throw_star { say "throwing star" }
}
$drew does ThrowStar;
Now with Rakudo Star I can apply an anonymous role directly:
$drew does role {
method throw_star { say "throwing star" }
};
Something I didn’t expect
The final change to the code was something unexpected. I got the following error:
===SORRY!===
Quoted method name requires parenthesized arguments at line 50, near "; # =>"
This was tied to this line of code:
$drew.'battle_cry'; # => Drew says zing!!!
I am not sure if this is a change to Perl6 spec but it now requires extra parenthesis:
$drew.'battle_cry'(); # => Drew says zing!!!
… and finally
My original post from beginning of the year was me just kicking the Rakudo tyres. I’m now looking forward to taking it out for a proper test drive around the block
Below is the complete revised code:
use v6;
use MONKEY_TYPING;
class Ninja {
has Str $.name is rw;
}
my Ninja $drew .= new( name => 'Drew' );
my Ninja $adam .= new( name => 'Adam' );
###########################################################
# Reopen Ninja class ("is also" does the biz)
# and add 'battle_cry' method
augment class Ninja {
method battle_cry {
say $.name ~ ' says zing!!!';
}
}
$drew.battle_cry; # => Drew says zing!!!
$adam.battle_cry; # => Adam says zing!!!
###########################################################
# add 'throw_star' method to $drew object by
# applying ("does") role to it (Singleton method)
$drew does role {
method throw_star { say "throwing star" }
};
$drew.throw_star; # => throwing a star
###########################################################
# call method dynamically
$drew.'battle_cry'(); # => Drew says zing!!!
###########################################################
# add "colour" method closing over $colour_name (ie. closure):
my $colour_name = 'black';
augment class Ninja {
method colour { say "{$.name}'s colour is $colour_name" }
}
$drew.colour; # => Drew's colour is black
$adam.colour; # => Adam's colour is black
###########################################################
# "defining a method dynamically on an instance that closes
# over local scope and accesses the instance’s state"
#
# Opps - Class method slipped in while working it out.
# $drew.^add_method() does a singleton method.. nice!
my $sword_symbol = '********';
$drew.^add_method( 'swing', method ( Str $sound_effect ) {
say "$.name: $sword_symbol $sound_effect";
} );
$drew.swing( 'slash!!' );
Happy halloween!
/I3az/


