I have a situation where I'd like to cache some calculations for use later. Let's say I have a list of allowed values. Since I'm going to be checking to see if anything is in that list I'm going to want it as a hash for efficiency and convenience. Otherwise I'd have to grep.
If I'm using Moose it would be nice if the cache was recalculated each time the list of allowed values is changed. I can do that with a trigger easy enough...
has allowed_values => (
is => 'rw',
isa => 'ArrayRef',
trigger => sub {
my %hash = map { $_ => 1 } @{$_[1]};
$_[0]->allowed_values_cache(\%hash);
}
);
has allowed_values_cache => (
is => 'rw',
isa => 'HashRef',
);
And the two will stay in sync...
$obj->allowed_values([qw(up down left right)]);
print keys %{ $obj->allowed_values_cache }; # up down left right
Now let's say I want a default for allowed_values
, simple enough
change...
has allowed_values => (
is => 'rw',
isa => 'ArrayRef',
trigger => sub {
my %hash = map { $_ => 1 } @{$_[1]};
$_[0]->allowed_values_cache(\%hash);
},
default => sub {
return [qw(this that whatever)]
},
);
...except setting the default doesn't call the trigger. To get it to DWIM I need to duplicate the caching.
has allowed_values => (
is => 'rw',
isa => 'ArrayRef',
trigger => sub {
$_[0]->cache_allowed_values($_[1]);
},
default => sub {
my $default = [qw(this that whatever)];
$_[0]->cache_allowed_values($default);
return $default;
},
);
sub cache_allowed_values {
my $self = shift;
my $values = shift;
my %hash = map { $_ => 1 } @$values;
$self->allowed_values_cache(\%hash);
return;
}
The Moose docs are explicit about trigger
not getting called when
the default is set, but it gets in the way. I don't like the
duplication there.
Is there a better way to do it?