如何使用从标量到arrayref的强制设置AoArrayrefs属性?

时间:2011-07-28 19:41:50

标签: perl multidimensional-array moose traits coerce

我想设置一个属性,该属性是一个arrayrefs数组,其中nonarrayrefs强制转换为数组引用。例如

[0,[0,0,0],[1,2,3]]变为[[0],[0,0,0],[1,2,3]]

另外,我也希望能够通过强制将元素推送或设置到AoA。这是我的尝试:

{
    package MyArray;
    use namespace::autoclean;
    use Moose::Util::TypeConstraints;
    use Moose;

    subtype 'My::ArrayRef' => as 'ArrayRef';
    coerce  'My::ArrayRef'
      => from 'Num|Str'
         => via {[$_]};

    has 'ents' => (
        traits  => ['Array'],
        is      => 'rw',
        isa     => 'ArrayRef[My::ArrayRef]',
        default => sub { [] },
        handles => {
            push      => 'push',
            get       => 'get',
            set       => 'set',
            elements  => 'elements',
            count     => 'count',
        },
        coerce => 1,
    );

    __PACKAGE__->meta->make_immutable;

}

use Modern::Perl;

my $a0 = MyArray->new( ents => [ 0, [ 0, 0, 0 ], [1,2,3] ] ) ;

use Data::Dumper;

print Dumper $a0;

$a0->set(0,'cat');
print Dumper $a0;
$a0->push(1.0);
print Dumper $a0;

1 个答案:

答案 0 :(得分:4)

类型需要在强制之前不匹配,但在之后成功。

这就是诀窍(经过测试):

my $array_ref = Moose::Util::TypeConstraints::find_type_constraint('ArrayRef');

# Create an alias so we don't affect others with our coercion.
subtype 'My::Data::Structure'
   => as 'ArrayRef[ArrayRef[Str|Num]]';

coerce 'My::Data::Structure'
   => from 'ArrayRef[ArrayRef[Str|Num]|Str|Num]'
      => via { [ map $array_ref->check($_) ? $_ : [ $_ ], @$_ ] };