Черты лося для многомерных структур данных

Прервать обработку внутренней переменной из вызовов переменной в вызовы объекта легко, используя обработчики 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 (я не думаю, что обычная строковая обработка была бы слишком полезна).

Другие вопросы по тегам