使用Attribute::Native::Trait处理程序很容易将内部变量从对变量的调用分解为对对象的调用。但是,如何处理多个数据结构呢?如果不让stash成为My:: stash::Attribute对象的arrayref,我想不出任何方法来处理下面的事情,而这个对象又包含一个My:: stash::Subattribute对象的arrayref,而这个子属性对象又包含一个arrayref My:: 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/);
这些是非常深奥的:
sub add_item {
my $self = shift;
my ($item) = @_;
push @{$self->_stash->{$item->{property}}{$item->{sub}}}, $item;
}
因此,add_item
取一个hashref item
,并将其压入存储中的数组键,该数组键由property
和sub
自己的键索引。
sub get_items {
my $self = shift;
my ($property, $subproperty) = @_;
return @{$self->_stash->{$property}{$subproperty}};
}
相反,get_item
有两个参数,一个$property
和一个$subproperty
,它在HoH中检索数组中相应的元素。
所以这里是考虑到使MooseX:
- 在非magic散列中没有办法坚持只有散列是值——这将是trait上可预测行为所必需的。在您的示例中,如果
_stash->{$property}
解析为标量,您会期望什么? -
add_item
将其深度硬编码为property
和sub
。 - 返回数组是不好的,它要求所有的元素被推到堆栈(返回refs)
首先,我不明白为什么一个普通的Moose Hash trait不能同时接受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)
中完全不同的helper中。我仍然只是使用上面指定的虚构的get
帮助器检索它。auto_deref
类型的功能是一个非常糟糕的主意。
简而言之,问问核心开发人员,他们会如何考虑在这种情况下扩展set
和get
,以接受 arrayref 作为键并采取适当的行动。我无法想象有一个有用的默认值ArrayRef键(我不认为常规的字符串化会太有用)。