Oh Well Back to the O'l Drawing Board

back_to_the_electronic_brain.jpg

Well that is the way I feel today, but at least, like Marvin, I am ready to start again. I tried in my last post to introduce a role into my D&D classes and all I ended up with what is what I started with, a muddle!

Well having another look at 'Intelligence', 'Characters' and 'Languages' I know that all 'Characters' have at least one language and they can learn more, the more 'intelligence' they have. So language ability is more of a trait of 'intelligence', rather than a role that intelligence fulfills. Hold on a 'trait' in Moose is just a role by another name so lets have a look?

package Languages;
use Moose::Role;

has 'languages' => (
	is         => 'ro',
	isa       =>'ArrayRef[Language]',
	default =>sub{[Language::Common->new();]},
);

So now now with this role I have moved the 'languages' attribute out of my 'Character' class and into the role. I also set this attribute up to take an ArrayRef of 'Language' Classes, and I even get to give it a default language to start out with. All good.


Now how about my learn_language sub. It needs 'Intelligence' from somewhere? Before when I had an 'Intelligence' role in my 'Character' class I just called it with '$self->current' and when it was a an attribute of a class I used '$self->intelligence->max_languages()'. I suppose I could pass it in as a param but I would have to add in some validation for that, or perhaps I could set it up so the sub can tell what is being passed and get the 'Intelligence' from that. I just can't assume that what ever comes in via the $self is going to have 'Intelligence' but wait maybe I can?

Well part of roles is also defining 'requirements' and we can do to a 'Moose' role, with what else, the 'requires' directive. Moose only allows you to require a 'sub' so you can't use it to make an other role or class required.

So I add that in along with my learn_language, and max_languages subs, after I set them up to use the required 'intelligence' attribute, like this;


package Languages;
use Moose::Role;
requires 'intelligence';

has 'languages' => (
	is  => 'ro',
	isa  =>'ArrayRef[Language]',
	default	=>sub{[Language::Common->new()]},
);

sub learn_language {
       my $self = shift;
       my ($language) = @_;
       return 
               if (scalar($self->languages) >= $self->max_languages());
       push(@{$self->languages()},$language);
}

sub max_languages {
	my $self = shift;
	return 1
		if ($self->intelligence()<8);
	return 8
		if ($self->intelligence() >=18);
  	my %additional = (8=>1,9=>1,10=>2,11=>2,12=>3,13=>3,14=>4,15=>4,16=>5,17=>6);
	return 1+$additional{$self->intelligence()};
}

Ok that looks alright, it certainly gives everything you would expect from a role, attributes methods and requirements so maybe I am on to something??

For now I will just fiddle with my Character class a little by dropping the intelligence role, adding in the languages role, then an intelligence attribute. Will have to work on this some more but that makes for a good next post.


package Character;
use Moose;
with qw( Languages );  

has 'name' =>(
	is		=>'ro',
	isa		=>'Str',
);
     
has 'intelligence' =>(
	is		=>'ro',
	isa		=>'Int',
	default=>0,
);

and off to the races;

use Character;
use Data::Dumper;
my $str = Character->new({name=>'sir_cumferace',intelligence=>12});

print $str->name()."\n";
print $str->max_languages()."\n";

$perl my_class.pl

What the Smeg??

Red_dwarf_polymorph.jpg


'Languages' requires the method 'intelligence' to be implemented by 'Character' at xbxbxbxe/Application/ToClass.pm line 134
	Moose::Meta::Role::Application::ToClass::check_required_methods('Moose::Meta::Role::Application::ToClass=HASH(0x2a382e4)', 'Moose::Meta::Role=HASH(0x2a4323c)', 'Moose::Meta::Class=HASH(0x2a38b9c)') called at C:/Dwimperl/perl/site/lib/Moose/Meta/Role/Application.pm line 55
...

Oh yes that little explanation from Steve. My 'Languages' role isn't very intelligent as it cant find what is obviously there. A little adjustment


use Moose;

has 'name' =>(
	is		=>'ro',
	isa		=>'Str',
);
     
has 'intelligence' =>(
	is		=>'ro',
	isa		=>'Int',
	default=>0,
);
with qw( Languages);  

and things work fine,


perl my_class.pl
sir_cumferace
4

even reads a little better, I With Intelligence comes Languages.

I Still say Moose's MOP need a little work, but what do I know;) It is top of the list at AmsterdamX soon, so we will see.

Goes right back to the old days of perl really. Go ahead try calling a sub in a script before you define it;) no majik here. Refreshing.


Leave a comment

About byterock

user-pic Long time Perl guy, a few CPAN mods allot of work on DBD::Oracle and a few YAPC presentations