Черты лося для многомерных структур данных - PullRequest
3 голосов
/ 15 июля 2011

Разбить обработку внутренней переменной от вызовов переменной до вызовов объекта легко с помощью обработчиков Attribute :: Native :: Trait.Тем не менее, как вы справляетесь с несколькими структурами данных?Я не могу придумать способ обработать что-то подобное ниже, не сделав stash arrayref объектов My :: Stash :: Attribute, которые, в свою очередь, содержат arrayref объектов My :: Stash :: Subattribute, который содержит arrayrefMy :: Stash :: Instance объекты.Это включает в себя много манипулирования и приведения данных на каждом уровне в стеке, пока я разбираюсь.

Да, я могу хранить элементы в виде плоского массива и затем отображать их при каждом чтении, но в ситуациипри частых операциях чтения и том, что большинство вызовов являются операциями чтения, поиск большого списка элементов массива требует большой обработки при каждом чтении по сравнению с простым внутренним индексированием элементов требуемым способом.

Существует ли расширение 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 Ответ

1 голос
/ 06 августа 2011

Это очень эзотерика:

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

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

Итак, add_item берет хеш-код item и помещает его в ключ массива в stash , индексируемом его собственными ключами 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.
  • возврат массивов - это плохо, требуется, чтобы все элементы были помещены в стек (возврат ссылок)

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

...