I’m beginning to use MooseX::Declare more and more, but this morning I realized I didn’t quite understand when the builder was getting called, and under what circumstances, so I wrote the following program to testing things out. Not so much a test of the code for some notion of correctness as a literal test of what is going on so I can be more informed.
use MooseX::Declare; class MagicBox { use Carp; has 'stuff' => ( is => 'rw', isa => 'HashRef', lazy_build => 1, ); method _build_stuff { carp 'invoking _build_stuff'; return {}; } method add_hash( HashRef $morestuff) { foreach ( keys %{$morestuff} ) { $self->stuff->{$_} = $morestuff->{$_}; } } method add_stuff( :$key, :$value ) { $self->stuff->{$key} = $value; }; }
Two things here. First, I put a carp statement in the builder, so I could see when it gets called. Second, I tried to make an overloaded method with the two versions of add_stuff and add_hash, but that failed. I know I saw something similar in the Piers Cawley yapc vid hosted on shadowcat but I guess it is another MooseX package.
Anyway, the following code exercises the class, and uses both clear and manually resetting the hash to see when the builder gets called, etc etc.
use Carp; use Data::Dumper; my $storage = MagicBox->new(); carp 'box created'; carp 'box contains ', Dumper $storage->stuff; $storage->add_hash( { one => 'thing one', two => 'thing two' } ); $storage->add_stuff( 'key' => 'three', 'value' => { 'cat' => 'hat', 'fish' => 'bowl' } ); carp 'not empty', Dumper $storage->stuff; carp 'calling clear'; $storage->clear_stuff; carp 'done calling clear'; carp 'empty', Dumper $storage->stuff; carp 'add stuff'; $storage->add_hash( { one => 'thing one', two => 'thing two' } ); carp 'not empty', Dumper $storage->stuff; carp 'manual reset'; $storage->stuff( {} ); carp 'empty', Dumper $storage->stuff; carp 'add stuff'; $storage->add_hash( { one => 'thing one', two => 'thing two' } ); carp 'not empty', Dumper $storage->stuff; 1;
Because I’m really only interested in when the builder is called, here is the output from the first half. It works exactly as advertised in the docs, but sometimes I like to see stuff rather than expect that the docs are right.
box created at test_moose.pl line 32 invoking _build_stuff at accessor stuff defined at test_moose.pl line 19 box contains $VAR1 = {}; at test_moose.pl line 34
The above output shows that first the box is created without calling the builder. Then when asking for the contents of stuff
, the builder is called. In other words, it is appropriately lazy, not building until necessary.
not empty$VAR1 = { 'three' => { 'cat' => 'hat', 'fish' => 'bowl' }, 'one' => 'thing one', 'two' => 'thing two' }; at test_moose.pl line 47
So this bit of output isn’t really necessary. I did it a different way first and learned that you can’t just call a method the same thing (add_stuff) with different arguments (a hash, and version two with named key value pair) and expect to get unique methods. Have to figure out that one still, but I don’t really need it right now.
Now the lazy_build clear_
method was exercised to see what happens with the builder
calling clear at test_moose.pl line 49 done calling clear at test_moose.pl line 51 invoking _build_stuff at accessor stuff defined at test_moose.pl line 19 empty$VAR1 = {}; at test_moose.pl line 52
Again as expected, clear_stuff
clears the resource, and it isn’t rebuilt until I ask to see what is in it.
The term ‘overloaded’ has a different meaning in Perl than it might have in other languages. This might be the reason you weren’t able to find how to do this. There is MooseX-MultiMethods on CPAN implementing this.
Yup, MooseX::MultiMethods is what you’re looking for.
Thanks for the pointers, I’ll look up MooseX::MultiMethods.