在我们的类中,我们有一个模式,我们创建一个属性来表示计算值.出于显而易见的原因,我们希望缓存计算的值,然后在其中一个基础值发生更改时使缓存无效.
所以我们目前有这个:
package FooBar;
use Moose;
has 'foo' => (
accessor => {
'foo' => sub {
my $self = shift;
if (@_ > 0) {
# writer
$self->{foo} = $_[0];
# reset fields that are dependant on me
$self->{bar} = undef;
}
# reader part;
return $self->{foo};
}
}
);
has 'bar' => (
accessor => {
'bar' => sub {
my $self = shift;
if (@_ > 0) {
# writer
$self->{bar} = $_[0];
}
# reader part;
$self->{bar} = calculate_bar($self->foo, $self->baz)
if (not defined($self->{bar}));
return $self->{bar};
}
}
);
sub calculate_bar { ... }
Run Code Online (Sandbox Code Playgroud)
当计算值取决于其他计算值时,这种长手法变得非常繁琐且容易出错.
有没有更聪明/更简单的方法让'bar'监控它依赖的属性与让'foo'知道谁依赖它?另外,如何通过哈希成员访问来避免设置栏?
Dan*_*Dan 11
如果我理解正确,您可以使用触发器在设置时清除属性.这是一个例子:
has 'foo' => (
is => 'rw',
trigger => sub{
my ($self) = @_;
$self->clear_bar;
}
);
has 'bar' => (
is => 'rw',
clearer => 'clear_bar',
lazy => 1,
default => sub{
my ($self) = @_;
return calculate_bar( ... );
}
);
Run Code Online (Sandbox Code Playgroud)
因此,对foo
via的任何写入都$obj->foo($newvalue)
将bar
被清除,并在下次访问时重新创建.
我认为你很可能通过使用遗传的属性隐式记忆来使你自己更难,当你可以让memoization显式使你的整个程序更透明
has [qw/foo bar baz/] => ( isa => 'Value', is => 'rw' );
use Memoize;
memoize('_memoize_this');
sub old_lazy_attr {
my $self = shift;
_memoize_this( $self->attr1, $self->attr2, $self->attr3 );
}
sub _memoize_this {
my @args = @_;
# complex stuff
return $result
}
Run Code Online (Sandbox Code Playgroud)
有关内部缓存的信息和控制,请参阅cpan的Memoize,还要记住,Memoized函数不能依赖于对象的状态.所以参数必须明确传递.