I'm beginning to realize that this is for beginners:
package Bad;
has 'arr' => ( is => 'rw', 'ArrayRef[Str]' );
package main;
my $bad = Bad->new(arr => [ "foo", "bar" ]);
print $bad->arr->[0], "\n";
Enter traits. I'm underwhelmed by the traits API, though. Have I misunderstood something? Can I get this API instead somehow? :
print $bad->arr->get(0), "\n";
Details
Review the canonical traits example from Moose::Meta::Attribute::Native::Trait::Array
package Stuff;
use Moose;
has 'options' => (
traits => ['Array'],
is => 'ro',
isa => 'ArrayRef[Str]',
default => sub { [] },
handles => {
all_options => 'elements',
add_option => 'push',
map_options => 'map',
filter_options => 'grep',
find_option => 'first',
get_option => 'get',
join_options => 'join',
count_options => 'count',
has_options => 'count',
has_no_options => 'is_empty',
sorted_options => 'sort',
},
);
no Moose;
1;
An object declared like that is used e.g.:
my $option = $stuff->get_option(1);
I really don't like that for one array attribute I get and have to manually name 11 methods in my Stuff class - one for every single operation that one can do to 'options'. Inconsistent naming is bound to happen and it is bloaty.
How do I instead (elegantly) get an API like:
my $option = $stuff->options->get(1);
Where all the methods from Moose::Meta::Attribute::Native::Trait::Array are implemented in a type-safe way?
Then all the operations on every single Array are named in exactly the same way...
(I'm actually using Mouse, but most of Mouse is identical to Moose)