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";
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)
I think that the best way to get your API into that format would be to create a new object for the options, and delegate the methods into it directly. Something like:
package Stuff;
use Moose;
use Stuff::Options;
has 'options' => (
'is' => "ro",
'isa' => "Stuff::Options",
'default' => sub { Stuff::Options->new },
);
no Moose;
1;
And then in Stuff/Options.pm
:
package Stuff::Options;
use Moose;
has '_options' => (
'is' => "ro",
'isa' => "ArrayRef[Str]",
'traits' => [ "Array" ],
'default' => sub { [] },
'handles' => [ qw(elements push map grep first get join count is_empty sort) ],
);
no Moose;
1;
This would allow code as in your example to work ($stuff->options->get(1)
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With