Yet another native traits in Moose

id:tokuhiromの示唆を得て,Native traits/AttributeHelpersについて考えてみた。
現在MooseではMX::AttributeHelpersが"Native traits"として組み込みになっているが,それにもかかわらずhas()の時点でtraits => ['Array']などとしないと使用できない。これは冗長だ。

use Any::Moose;
has foo => (
    is  => 'ro',
    isa => 'ArrayRef',
    traits => ['Array'], # 冗長
    handles => {
        # ...
    },
);

"isa"でArrayRefを指定しているのだから,traits => ['Array']は明らかに冗長である。
ところで,native traitsの仕組みは委譲の一種と考えることができる。その方向で考えると,既存のMooseの委譲メカニズムでこれに近いことができることに気づく。

#!perl -w
use 5.010;
package My::HashRef;
use Any::Moose;
sub store{
    my($hashref, $key, $value) = @_;
    $hashref->{$key} = $value;
}

sub keys{
    my($hashref) = @_;
    return keys %{$hashref};
}
package Foo;
use Any::Moose;

has map => (
    is  => 'ro',
    isa => 'My::HashRef',
    default => sub{ My::HashRef->new },

    handles => {
        map_keys  => 'keys',
        map_store => 'store',
    },
);

package main;

my $foo = Foo->new();
$foo->map_store(hoge => 42);
$foo->map_store(fuga => 43);

say $foo->dump;
say join ' ', $foo->map_keys; # => fuga hoge
__END__

もちろん,今はこれをオブジェクトに対してしか行えないので,たとえば,isa => 'Str'などとすることはできない。このあたりをもう少し詰めれば,委譲メカニズムのちょっとした拡張でtraitsの指定を省略することができるかもしれない。