I've had this exact requirement several times in the past, and today I actually had to do it from the metaclass, which meant no BUILD tweaking allowed. Anyway I felt it would be good to share since it basically does exactly what ether mentioned:
'It would allow marking attributes "this is lazy, because it depends
on other attribute values to be built, but I want it to be poked
before construction finishes."'
However, derp derp I have no idea how to make a CPAN module so here's some codes:
https://gist.github.com/TiMBuS/5787018
Put the above into Late.pm and then you can use it like so:
package Thing;
use Moose;
use Late;
has 'foo' => (
is => 'ro',
default => sub {print "setting foo to 10\n"; 10},
);
has 'bar' => (
is => 'ro',
default => sub {print 'late bar being set to ', $_[0]->foo*2, "\n"; $_[0]->foo*2},
late => 1,
);
#If you want..
__PACKAGE__->meta->make_immutable;
1;
package main;
Thing->new();
#`bar` will be initialized to 20 right now, and always after `foo`.
#You can even set `foo` to 'lazy' or 'late' and it will still work.
default
for that? I thought the point oflazy
was to postpone creating the attribute value until first use. If you need all attributes to be set at object construction,default
seems more useful. Or, you can provide your ownBUILD
method. – GizzardBUILD
instead but it's nicer to have a method per-attribute. And if you're going to have a method per attribute to compute the value then it may as well be a builder. But if a builder is going to access other attributes then the built attribute needs to be lazy to be sure that they've been initialized. And there isn't a "lazy, but only a little bit lazy" attribute option :) – Epistyle