Sch*_*ern 7 perl caching moose
我有一种情况,我想缓存一些计算以供以后使用.假设我有一个允许值列表.由于我将要检查该列表中是否有任何内容,因此我希望将其作为效率和便利的哈希.否则我必须要grep.
如果我正在使用Moose,那么每次更改允许值列表时重新计算缓存都会很好.我能用触发器轻松做到这一点......
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',
);
Run Code Online (Sandbox Code Playgroud)
两者将保持同步......
$obj->allowed_values([qw(up down left right)]);
print keys %{ $obj->allowed_values_cache }; # up down left right
Run Code Online (Sandbox Code Playgroud)
现在让我们说我想要一个默认值allowed_values
,简单的变化......
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)]
},
);
Run Code Online (Sandbox Code Playgroud)
...除了设置默认值不会调用触发器.要将其转换为DWIM,我需要复制缓存.
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;
}
Run Code Online (Sandbox Code Playgroud)
Moose文档明确表示trigger
在设置默认值时不会被调用,但它会妨碍.我不喜欢那里的重复.
有没有更好的方法呢?
我最近遇到了这个问题,在询问#moose
频道后,被告知这样处理:
标记cache_allowed_values
为a lazy_build
,_build_cache_allowed_values
引用当前值allowed_values
,并将写入触发器allowed_values
清除cache_allowed_values
.
这样,无论要求或保存的是什么顺序,他们总是以最少的工作量做对.
has cache_allowed_values => (is => 'ro', lazy_build => 1);
sub _build_cache_allowed_values {
return { map { $_ => 1 } @{shift->allowed_values} };
}
has allowed_values => (
is => 'rw',
trigger => sub { shift->clear_cache_allowed_values },
default => ...,
);
Run Code Online (Sandbox Code Playgroud)