YAMADDP (Yet Another Moose ADD Post)
Well there is always more things to post on and today I found yet another.
You might remember this post where I was setting starting money for player characters and you might remember this post where I pinched the idea from.
There was a flaw with this as it is true I was not longer able to set starting gold or hit points by doing something this
return $self->current_gp()
if ($self->current_gp());
or
return $self->current_hps()
if ($self->current_hps());
and it worked well for a one off but as I created more classes and monsters I saw that the '_build_hps' and '_starting_gp' where better off being simply methods that 'set' the attribute values when called rather than builders when the attribute is set.
As well I noticed that while for Hit Points the worked well but it was as a little disconcerting as I bought stuff my starting GP balance was going down as well as my current balance so made it hard to see how many GPs I has spent.
So what to do
Well a quick look on Map of CPAN and I found what I hope is a better solution. MooseX::SetOnce
A simple enough
...
use MooseX::SetOnce;
has hit_points => (
is=>'rw',
isa=>'Int',
default=>0,
traits => [ qw(SetOnce) ],
init_arg => undef,
alias => [ qw(HP hp) ],
);
and move my '_build_hps' off to its own 'sub' and then give it a try
...
my $pc = $new->creator(...)
my $pc->build_hps
print "HP=".$pc->HP
and then give it a go
perl new_pd.pl
cannot change value of SetOnce attribute hit_points at C:/Dwimperl/perl/site/lib
/MooseX/SetOnce.pm line 35
...
Oops not what I was looking for. A quick look at my has and I noticed a 'default=>0' so I removed that and then I give it another try and I got this
HP=5
Now if I add in a line and try to change it
print $pc->HP
$pc->HP(10000);
I will get the expected exception
D:\blogs>perl ht_test.pl
cannot change value of SetOnce attribute hit_points at C:/Dwimperl/perl/site/lib
/MooseX/SetOnce.pm line 35
Perfect I can see this coming in very handy as time goes on especially for any tomb-stone data I might have.
Now that default issue is something to look out for as I use defaults all over the place. I will to make a few little changes for example I have to account that HP no longer start out as '0' but as undef but I can live with that.
I wonder if a patch to allow for defaults is in order, something to look at?
Anyway here is a cute moose picture to end this
It should be possible to usefully use a default with a SetOnce attribute, provided you make the attribute lazy.
(However, this will make read accesses to the accessor count as "setting it" if they result in the default being returned. That may or may not be what you want.)
Yep tried that does not do what I want
so
has hit_points => (
is=>'rw',
isa=>'Int',
lazy=>1,
default=>0,
traits => [ qw(SetOnce) ],
);
would be much the the same as
has hit_points => (
is=>'ro',
isa=>'Int',
init_arg => undef,
default=>0,
);
except you can set it only once!
so this would work
$hps->build_hps();
print $hps->HP;
5
and like you said this will not
print $hps->HP;
$hps->build_hps();
0
error
Cheers