Черты лося для многомерных структур данных
Прервать обработку внутренней переменной из вызовов переменной в вызовы объекта легко, используя обработчики Attribute:: Native:: Trait. Тем не менее, как вы справляетесь с несколькими структурами данных? Я не могу придумать какой-либо способ обработки чего-то подобного приведенному ниже без создания тайника для arrayref объектов My:: Stash:: Attribute, которые, в свою очередь, содержат arrayref объектов My:: Stash:: Subattribute, который содержит arrayref My:: Stash:: Instance объекты. Это включает в себя много манипулирования и приведения данных на каждом уровне в стеке, пока я разбираюсь.
Да, я могу хранить элементы в виде плоского массива, а затем выполнять grep при каждом чтении, но в ситуации частых чтений, когда большинство вызовов считываются, поиск большого списка элементов массива требует большой обработки при каждом чтении и просто индексирование элементов внутри, как нужно.
Существует ли расширение MooseX, которое может обрабатывать подобные вещи с помощью методов, создающих обработчики, вместо того, чтобы просто обрабатывать средство доступа для чтения как хэш-адрес и изменять его на месте? Или мне просто лучше забыть о том, чтобы делать такие вещи с помощью вызова метода, и просто делать это как есть?
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/);
1 ответ
Это очень эзотерика:
sub add_item {
my $self = shift;
my ($item) = @_;
push @{$self->_stash->{$item->{property}}{$item->{sub}}}, $item;
}
Так add_item
принимает хешреф item
и помещает его в ключ массива в хранилище, индексируемом его собственными ключами property
, а также sub
,
sub get_items {
my $self = shift;
my ($property, $subproperty) = @_;
return @{$self->_stash->{$property}{$subproperty}};
}
Наоборот, get_item
принимает два аргумента, $property
и $subproperty
и он получает соответствующие элементы в массиве в HoH.
Итак, вот что стоит сделать из этого MooseX:
- В немагическом хеше нет никакого способа утверждать, что только хэши являются значениями - это потребуется для предсказуемого поведения черты. Как и в вашем примере, что вы ожидаете, если
_stash->{$property}
разрешено в скаляр. add_item
имеет твердую глубинуproperty
а такжеsub
,- возвращать массивы плохо, требуется, чтобы все элементы были помещены в стек (return refs)
Теперь, во-первых, я не понимаю, почему обычная черта Moose Hash не может принимать ссылки на массивы как для сеттера, так и для геттера.
->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])`
Когда дело доходит до того, что назначение будет массивом, а не слотом для хэша, я предполагаю, что вам просто нужно встроить это в совершенно другого помощника в черте, push_to_array_or_create([$property, $subproperty], $value)
, Я бы все равно просто извлек это с вымышленным get
помощник указан выше. auto_deref
Функциональность типа довольно плохая идея.
Короче спросите основного разработчика о том, что они подумают о расширении set
а также get
в этом контексте принять ArrayRefs в качестве ключей и действовать соответствующим образом. Я не могу себе представить, что есть полезные значения по умолчанию для ключей ArrayRef (я не думаю, что обычная строковая обработка была бы слишком полезна).