如何在Moose中最好地使用默认值触发访问器?

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在设置默认值时不会被调用,但它会妨碍.我不喜欢那里的重复.

有没有更好的方法呢?

Ran*_*rtz 7

我最近遇到了这个问题,在询问#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)

  • 我不确定我会效仿.你能写出来吗? (2认同)