I have two object attributes which require expensive calculations, so I'd like them to be lazy. They're most efficiently calculated together, so I'd like to calculate them at the same time. Does Moose provide a way to do this?
What I'd like is something like 'default' or 'builder' but instead of returning the default value it directly sets attributes. The return value would be ignored.
has max_things =>
is => 'rw',
isa => 'Int',
lazy => 1,
xxxxx => '_set_maxes';
has max_pairs =>
is => 'rw',
isa => 'Int',
lazy => 1,
xxxxx => '_set_maxes';
# Let's just assume this is an expensive calculation or the max_*
# attributes are used rarely and a lot of objects are created.
sub _set_maxes {
my $self = shift;
if( $self->is_32_bit ) {
$self->max_things(2**31);
$self->max_pairs(12345 * 2);
}
else {
$self->max_thing(2**63);
$self->max_pairs(23456 * 2);
}
return;
}
NOTE: I could write my own 'reader' or use 'around', but I'd rather keep it declarative and let Moose do the work. I also could make a new object just to store the paired values, but it seems like overkill for just two values.
I wouldn't say this is especially elegant, but it works...
use v5.14;
use warnings;
package Goose {
use Moose;
has max_things => (
is => 'rw',
isa => 'Int',
lazy => 1,
default => sub { shift->_build_maxes->max_things },
);
has max_pairs => (
is => 'rw',
isa => 'Int',
lazy => 1,
default => sub { shift->_build_maxes->max_pairs },
);
sub is_32_bit { 1 }
sub _build_maxes {
my $self = shift;
warn "Running builder...";
if( $self->is_32_bit ) {
$self->max_things(2**31);
$self->max_pairs(12345 * 2);
}
else {
$self->max_thing(2**63);
$self->max_pairs(23456 * 2);
}
$self; # helps chaining in the defaults above
}
}
my $goose = Goose->new;
say $goose->max_things;
say $goose->max_pairs;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With