多维数据结构的驼鹿特征

发布于 2024-11-20 00:29:27 字数 1286 浏览 8 评论 0原文

使用 Attribute::Native::Trait 处理程序可以轻松地将内部变量的处理从对变量的调用分解为对对象的调用。但是,如何处理多种数据结构呢?我想不出任何方法来处理类似下面的事情,而不使存储成为 My::Stash::Attribute 对象的 arrayref,而 My::Stash::Attribute 对象又包含 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/);

Breaking out handling an internal variable from calls on the variable into calls on the object is easy using the Attribute::Native::Trait handlers. However, how do you deal with multiple data structures? I can't think of any way to handle something like the below without making the stash an arrayref of My::Stash::Attribute objects, which in turn contain an arrayref of My::Stash::Subattribute objects, which contains an arrayref My::Stash::Instance objects. This includes a lot of munging and coercing the data each level down the stack as I sort things out.

Yes, I can store the items as a flat array and then grep it on every read, but in a situation with frequent reads and that most calls are reads, grepping against a large list of array items is a lot of processing every read vs just indexing the items internally in the way needed.

Is there a MooseX extension that can handle this sort of thing via handlers creating methods, instead of just treating the read accessor as the hashref it is and modifying it in place? Or am I just best off forgetting about doing things like this via method call and just doing it as-is?

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/);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

老娘不死你永远是小三 2024-11-27 00:29:27

这些非常深奥:

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

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

因此 add_item 接受一个 hashref item,并将其推送到 stash 中由它自己的键索引的数组键 属性

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

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

相反,get_item 采用两个参数,一个 $property 和一个 $subproperty,它检索 HoH 中数组中的适当元素。

因此,MooseX 的关注点如下:

  • 在非 Magic 哈希中,无法坚持只有哈希才是值——这对于特征的可预测行为是必需的。正如您的示例中所示,如果 _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])`

当谈到让目的地是一个数组而不是一个哈希槽时,我认为您只需将其构建到特征中的一个完全不同的帮助器中, push_to_array_or_create([$property, $subproperty], $value)。我仍然会使用上面指定的虚构的 get 帮助程序来检索它。 auto_deref 类型的功能是一个非常糟糕的主意。

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

These are very esoteric:

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

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

So add_item takes an hashref item, and pushes it onto an array key in stash indexed by it's own keys property, and sub.

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

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

Conversely, get_item takes two arguments, a $property and a $subproperty and it retrieves the appropriate elements in a Array in a HoH.

So here are the concerns into making it MooseX:

  • There is no way in a non-Magic hash to insist that only hashes are values -- this would be required for predictable behavior on the trait. As in your example, what would you expect if _stash->{$property} resolved to a scalar.
  • add_item has it's depth hardcoded to property and sub.
  • returning arrays is bad, it requires all of the elements to be pushed onto the stack (return refs)

Now firstly, I don't see why a regular Moose Hash trait couldn't accept array refs for both the setter and getter.

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

This would certainly make your job easier, if your destination wasn't an array:

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])`

When it comes to having the destination be an array than a hash slot, I assume you'd just have to build that into a totally different helper in the trait, push_to_array_or_create([$property, $subproperty], $value). I'd still just retrieve it with the fictional get helper specified above. auto_deref type functionality is a pretty bad idea.

In short ask a core developer on what they would think about extending set and get in this context to accept ArrayRefs as keys and act appropriately. I can't imagine there is a useful default for ArrayRef keys (I don't think regular stringification would be too useful.).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文