A simple “show me” program to understand what lazy_build, etc does

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.

Advertisements

3 thoughts on “A simple “show me” program to understand what lazy_build, etc does

  1. 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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s