【问题标题】:can Perl Moose objects have directly an array/hash attribute?Perl Moose 对象可以直接具有数组/哈希属性吗?
【发布时间】:2020-12-12 09:07:04
【问题描述】:

在 Perl 中可以做这样的事情吗?

package Person;
use Moose;

has 'friends' => ( is => 'rw', isa => 'Array', default => () );

我看到 perl 编译器不接受这种特定的语法,但是我使用了错误的语法,还是根本不可能?我必须改用数组引用吗?

我对 perl 很陌生,所以这个问题可能很愚蠢,我觉得答案是“不”,但我没有找到任何关于它的提及。

提前致谢

【问题讨论】:

  • 看到您无法将数组传递给访问器,无法从访问器接收一个数组,或者将数组存储为哈希(或其他任何 Moose 对象),我不知道甚至知道您甚至认为“数组属性”是什么。你能解释一下“数组属性”是什么意思吗?
  • default => () 没有意义。这只是'default'的一种奇怪的写法。
  • 谢谢,这对我来说基本上意味着它无法完成。我仍然很习惯 PHP,其中数组被视为普通变量,所以我不知道数组不能传递给访问器等。
  • 基本意思是什么不能做?数组是 Perl 中的普通变量。数组不能传递给访问器,因为数组不能传递给 subs,因为 subs 只能接受一个标量列表作为参数。
  • @amik:你想做的可以做,但你没有描述你想做什么。显示一些代码来演示您希望如何使用此属性

标签: arrays perl attributes moose


【解决方案1】:

“列表”有很多定义。假设您的意思是 Person 对象的集合或有序集合,我将使用一个数组,我将使用引用传递给访问器

has friends => (
   is      => 'rw',
   isa     => 'ArrayRef[Person]',
   default => sub { [] },
);

push @{ $o->friends }, $person;

for (@{ $o->friends }) {
   ...
}

您可以使用Moose::Meta::Attribute::Native::Trait::Array 添加有用的方法。

has friends => (
   traits  => [qw( Array )],
   is      => 'rw',
   isa     => 'ArrayRef[Person]',
   default => sub { [] },
   handles => {
      push_friends => 'push',
   },
);

$o->push_friends($person);

for (@{ $o->friends }) {
   ...
}

【讨论】:

    【解决方案2】:

    这不是你要问的,但是看看数组特征 - http://search.cpan.org/dist/Moose/lib/Moose/Meta/Attribute/Native/Trait/Array.pm。由于实例的所有值都存储在 hashref 中,因此您不能存储标量值以外的任何内容,这意味着您需要使用引用。这将处理您使用内部数组引用所需的所有样板。

    package Person;
    use Moose;
    
    has 'friends' => ( is => 'ro', 
                       traits  => ['Array'],
                       isa => 'ArrayRef[Str]',
                       default => sub { [] },
                       handles => {
                                     all_friends    => 'elements',
                                     add_friend     => 'push',
                                     map_friends    => 'map',
                                     filter_friends => 'grep',
                                     find_friend    => 'first',
                                     get_friend     => 'get',
                                     join_friends   => 'join',
                                     count_friends  => 'count',
                                     has_friends    => 'count',
                                     has_no_friends => 'is_empty',
                                     sorted_friends => 'sort',
                                 },
    
                     );
    

    【讨论】:

    • +1 我认为数组特征是 OP 寻求的答案,同时需要为默认提供代码参考
    【解决方案3】:

    作为一个至少使 get/set 更容易的简单答案,您可以编写自己的访问器函数来将数组 ref 包装到数组中。例如:

    package Person;
    use Moo;
    
    has 'friendsRef' => ( is => 'rw', default => sub { []; } );
    
    ## A 'set/get' wrapper for friendsRef
    sub Person::friends {
      my ($self, @list) = @_;
      return @{$self->friendsRef} unless $#list>=0;
      return $self->friendsRef(\@list);
    }
    
    ## Example bonus function for adding to list
    sub Person::addFriends {
      my ($self, @list) = @_;
      return push(@{$self->friendsRef}, @list);
    }
    

    示例代码用法可能是:

    my $p = Person->new();
    
    $p->friends('Dave','Jerry');
    print "Friends are: ",join(', ',$p->friends()),"\n";
    
    $p->friends('Bob','Dave');
    print "Friends are: ",join(', ',$p->friends()),"\n";
    
    $p->addFriends('Joe','Cletus');
    print "Friends are: ",join(', ',$p->friends()),"\n";
    
    ## Note that "$p->friends()" is not a scalar, it's a sub returning an array,
    ## so instead of "$#{$p->friends()}" you'd want "scalar($p->friends())"
    print "Number of friends is ",scalar($p->friends()),"\n";
    

    输出是:

    Friends are: Dave, Jerry          
    Friends are: Bob, Dave            
    Friends are: Bob, Dave, Joe, Cletus                                 
    Number of friends is 4            
    

    【讨论】:

      猜你喜欢
      • 2021-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-22
      • 2014-04-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多