Moose:当属性值改变时,计算的缓存结果到期了吗?

cls*_*ott 5 perl moose

在我们的类中,我们有一个模式,我们创建一个属性来表示计算值.出于显而易见的原因,我们希望缓存计算的值,然后在其中一个基础值发生更改时使缓存无效.

所以我们目前有这个:

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)

因此,对foovia的任何写入都$obj->foo($newvalue)bar被清除,并在下次访问时重新创建.

  • 从可维护性的角度来看,它也是倒退的; bar-depends-on-foo在逻辑上是bar的属性,而不是foo (2认同)

Eva*_*oll 5

我认为你很可能通过使用遗传的属性隐式记忆来使你自己更难,当你可以让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函数不能依赖于对象的状态.所以参数必须明确传递.