【问题标题】:Moose traits for multdimensional data structures多维数据结构的 Moose 特征
【发布时间】:2011-07-14 20:20:36
【问题描述】:

使用 Attribute::Native::Trait 处理程序很容易将内部变量从对变量的调用拆分为对对象的调用。但是,如何处理多个数据结构?我想不出任何方法来处理类似下面的事情而不使存储成为 My::Stash::Attribute 对象的数组引用,而这些对象又包含 My::Stash::Subattribute 对象的数组引用,其中包含一个数组引用我的::Stash::Instance 对象。这包括在我整理事情时对堆栈的每一层进行大量的修改和强制数据。

是的,我可以将项目存储为一个平面数组,然后在每次读取时对其进行 grep,但是在频繁读取并且大多数调用都是读取的情况下,对大量数组项进行 grep读取而不是按需要的方式在内部索引项目。

是否有一个 MooseX 扩展可以通过处理程序创建方法来处理这类事情,而不是仅仅将读取访问器视为 hashref 并对其进行修改?还是我最好还是忘记通过方法调用来做这样的事情并按原样做?

use strict;
use warnings;
use 5.010;

package My::Stash;
use Moose;

has '_stash' => (is => 'ro', isa => 'HashRef', default => sub { {} });

sub add_item {
  my $self = shift;
  my ($item) = @_;

  push @{$self->_stash->{$item->{property}}{$item->{sub}}}, $item;
}

sub get_items {
  my $self = shift;
  my ($property, $subproperty) = @_;

  return @{$self->_stash->{$property}{$subproperty}};
}

package main;
use Data::Printer;

my $stash = My::Stash->new();

for my $property (qw/foo bar baz/) {
  for my $subproperty (qw/fazz fuzz/) {
    for my $instance (1 .. 2) {
      $stash->add_item({ property => $property, sub => $subproperty, instance => $instance })
    }
  }
}

p($_) for $stash->get_items(qw/baz fuzz/);

【问题讨论】:

    标签: perl multidimensional-array moose


    【解决方案1】:

    这些非常深奥:

    sub add_item {
      my $self = shift;
      my ($item) = @_;
    
      push @{$self->_stash->{$item->{property}}{$item->{sub}}}, $item;
    }
    

    所以add_item 需要一个 hashref item,并将其推送到 stash 中的一个数组键上,该数组键由它自己的键 propertysub 索引。

    sub get_items {
      my $self = shift;
      my ($property, $subproperty) = @_;
    
      return @{$self->_stash->{$property}{$subproperty}};
    }
    

    相反,get_item 接受两个参数,一个 $property 和一个 $subproperty,它在 HoH 中检索 Array 中的适当元素。

    以下是制作 MooseX 的担忧:

    • 在非魔法散列中没有办法坚持只有散列是值——这对于特征的可预测行为是必需的。与您的示例一样,如果 _stash->{$property} 解析为标量,您会期望什么。
    • add_item 已将其深度硬编码为 propertysub
    • 返回数组不好,它需要将所有元素压入堆栈(返回引用)

    首先,我不明白为什么常规 Moose Hash 特征不能同时接受 setter 和 getter 的数组引用。

    ->set( [qw/ key1 key2/], 'foo' )    
    ->get( [qw/ key1 key2/] )
    

    如果您的目的地不是数组,这肯定会让您的工作更轻松:

    sub add_item {
       my ( $self, $hash ) = @_;
       $self->set( [ $hash->{property}, $hash->{subproperty} ], $hash );
    }
    
    # get items works as is, just pass in an `ArrayRef`
    # ie, `->get([$property, $subproperty])`
    

    当目标是一个数组而不是一个哈希槽时,我假设你只需要在 trait 中将它构建到一个完全不同的帮助器中,push_to_array_or_create([$property, $subproperty], $value)。我仍然会使用上面指定的虚构get 助手来检索它。 auto_deref 类型功能是一个非常糟糕的主意。

    简而言之,询问核心开发人员他们会如何考虑在这种情况下扩展 setget 以接受 ArrayRefs 作为键并采取适当的行动。我无法想象 ArrayRef 键有一个有用的默认值(我认为常规字符串化不会太有用。)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-25
      • 2018-07-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多