代码之家  ›  专栏  ›  技术社区  ›  Schwern

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

  •  7
  • Schwern  · 技术社区  · 15 年前

    稍后。假设我有一个允许值的列表。因为我要 我想看看名单上有没有我想要的 为了效率和方便的散列。否则我就得爬了。

    如果我用的是驼鹿的话,最好每个缓存都重新计算 更改允许值列表的时间。我可以用一个 很容易触发。。。

    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',
    );
    

    两人将保持同步。。。

    $obj->allowed_values([qw(up down left right)]);
    print keys %{ $obj->allowed_values_cache };   # up down left right
    

    现在假设我希望 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)]
        },
    );
    

    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;
    }
    

    驼鹿医生明确表示 trigger 什么时候没接到电话 重复。

    有更好的办法吗?

    2 回复  |  直到 15 年前
        1
  •  7
  •   Brad Gilbert    15 年前

    我最近遇到了这个问题 #moose

    cache_allowed_values 作为一个 lazy_build ,有 _build_cache_allowed_values 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 => ...,
    );
    
        2
  •  2
  •   Schwern    15 年前

    我想你真的想 allowed_values 成为一个独立的数据结构,具有所需的效率和排序属性。既然看起来你不在乎订货,为什么不:

    has 'allowed_values' => (
        traits  => ['Hash'],
        isa     => HashRef[Bool],
        default => sub { +{} },
        handles => {
            _add_allowed_value   => 'set',
            remove_allowed_value => 'delete',
            value_is_allowed     => 'exists',
            allowed_values       => 'keys',
        },
    );
    
    method add_allowed_value(Str $value){
        $self->_add_allowed_value( $value, 1 );
    }
    

    编辑:

    如果您希望用户认为这是一个列表,那么:

    use MooseX::Types::Moose qw(Bool ArrayRef HashRef);
    use MooseX::Types -declare => ['ListHash'];
    subtype ListHash, as HashRef[Bool];
    
    coerce ListHash, from ArrayRef, via { +{ map { $_ => 1 } @$_ } };
    
    has 'allowed_values' => (
        # <same as above>
        isa    => ListHash,
        writer => 'set_allowed_values',
        coerce => 1,
    );
    

    现在你可以设置 比如:

    my $instance = Class->new( allowed_values => [qw/foo bar/] );
    $instance->set_allowed_values([qw/foo bar baz/]);
    

    像这样访问它们:

    my @allowed_values = $instance->allowed_values;
    ... if $instance->value_is_allowed('foo');
    

    $instance->remove_allowed_value('foo');
    $instance->add_allowed_value('gorch');
    

    这会向用户隐藏任何底层实现的详细信息。

    顺便问一下,构建散列并使用它是否比对3个元素进行线性扫描快得多?