[sf-perl] the mouse with antlers

Joseph Brenner doomvox at gmail.com
Mon Apr 9 17:26:19 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...
>
> Soo...  Forgive me if I'm not reading this correctly, but it sounds like you're concerned that when subject is lazily built, you won't be able to get id's value as it won't have been built yet?
>
> Ignore the rest if I've misread this :)
>
> 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