Search code examples
arraysperlmoosetraits

Moose array attributes: how do I use a set method?


I want to define an array as attribute of a class and fill it with some data when the class is instantiated.

I thought it would be possible to use a $self->attribute->set($id, $value) method in order to set an element on a given index. At least that's what I understood from the Moose documentation.

But when I try

use Data::Dumper qw( Dumper );
use Moose;

has cells => (
    is => 'rw',
    traits  => ['Array'],
    isa     => 'ArrayRef',
    default => sub { [] },
);

my $app = __PACKAGE__->new();
$app->cells->set($_, $_) for 0..3;
print(Dumper($app->cells));

I get

Can't call method "set" on unblessed reference

How can I do I make set work?


Solution

  • use Data::Dumper qw( Dumper );
    use Moose;
    
    has cells => (
        is => 'rw',
        traits  => ['Array'],
        isa     => 'ArrayRef',
        default => sub { [] },
        handles => {                   # <---
           set_cell => 'set',          # <---
        },                             # <---
    );
    
    my $app = __PACKAGE__->new();
    $app->set_cell($_, $_) for 0..3;   # <---
    print(Dumper($app->cells));
    

    Despite claims to the contrary in the comments, it works fine in BUILD too.

    use Data::Dumper qw( Dumper );
    use Moose;
    
    has cells => (
        is => 'rw',
        traits  => ['Array'],
        isa     => 'ArrayRef',
        default => sub { [] },
        handles => {
           set_cell => 'set',
        },
    );
    
    sub BUILD {
        my ($self) = @_;
        $self->set_cell($_, $_) for 0..3;
    }
    
    my $app = __PACKAGE__->new();
    print(Dumper($app->cells));