[sf-perl] the mouse with antlers

Joseph Brenner doom at kzsu.stanford.edu
Mon Apr 9 17:28:30 PDT 2012

Chris Weyl <cweyl at alumni.drew.edu> wrote:
> Joseph Brenner <doom at kzsu.stanford.edu> wrote:
>> I find myself worrying about what I would do if I needed more than two
>> stages, instantiation and lazy access.  Like what if I wanted to put
>> the id in the subject?
>> I'd have to do a gratuitous access of id to make sure it was defined
>> before accessing subject...

> Lazily built attributes are built the first time they're read, if they haven't been explicitly set in the constructor call.  Basically, attributes are set:
> * via explicit value in new()
> * at new() if a default/builder is provided and the attribute is not lazy
> * at any access if a default/builder has been provided, the attribute is not set, and the attribute is lazy
> So long as there are no circular references between your attribute defaults/builders (exciting!), you can have them access any other lazily built attribute without worrying if it has been built already or not.  In your musing above, subject's default/builder can rely on id being set when it accesses id, as id will be built on that access if it has not already been built.

And once I heard you say this, it was obvious.  Now I'm not sure why I
was worried about it.

Stuff like this works fine:

package Trial::LazyChain;
use Mouse;
has name        => (is => 'rw',  isa => 'Str', required => 1);
has id          => (is => 'rw',  isa => 'Str', default => '001');
has title       => (is => 'rw',  isa => 'Str',
  default =>
     sub{ 'Report for name: ' . $_[0]->name }, lazy => 1);
has full_title  => (is => 'rw',  isa => 'Str',
  default =>
     sub{ $_[0]->title . ' and id: ' . $_[0]->id  }, lazy => 1);

And later:

use Trial::LazyChain;
my $td = Trial::LazyChain->new( name => 'yawnchair' );
print $td->full_title, "\n";
 # Report for name: yawnchair and id: 001

More information about the SanFrancisco-pm mailing list