in reply to Moose Trait to Add a Method to an Attribute

We can still imagine a simpler interface: the apply_to_list method that takes a code reference and applies it to each element of the list.

But that's not exactly what we imagined. Is it possible to create a trait (or modify the Array trait) in a way that it adds a new apply method to the attribute which we can use in delegation, i.e. something like

Maybe just copy what moose itself does?

untested, with minimum modification of https://metacpan.org/source/ETHER/Moose-2.1806/lib/Moose/Meta/Method/Accessor/Native/Array/sort_in_place.pm

update: tested, seems to work

#!/usr/bin/perl -- package Moose::Meta::Method::Accessor::Native::Array::apply; our $VERSION = '2.1806'; use strict; use warnings; use Params::Util (); use Moose::Role; with 'Moose::Meta::Method::Accessor::Native::Array::Writer'; sub _maximum_arguments { 1 } sub _inline_check_arguments { my $self = shift; return ( 'if (@_ && !Params::Util::_CODELIKE($_[0])) {', $self->_inline_throw_exception( InvalidArgumentToMethod => 'argument = +> $_[0],'. 'method_name = +> "apply",'. 'type_of_argument = +> "code reference",'. 'type = +> "CodeRef",', ) . ';', '}', ); } sub _adds_members { 0 } sub _potential_value { my $self = shift; my ($slot_access) = @_; return '[ $_[0] ' . '? map { $_[0]->($_) } @{ (' . $slot_access . ') } ' . ': @{ (' . $slot_access . ') } ]'; } sub _return_value { '' } no Moose::Role; 1; package My; use Moose; has list => ( is => 'rw', isa => 'ArrayRef[Str]', traits => [qw[ Array ]], handles => { add_to_list => 'push', list_elements => 'elements', map_list => 'map', apply_to_list => 'apply', }, ); package main; my $obj = My->new; $obj->add_to_list(qw( a b c )); $obj->apply_to_list(sub { uc }); print "$_\n" for $obj->list_elements; __END__ A B C

Looks like Moose makes copies of arrays with potential_value ... very confusing/disgusting

  • Comment on Re: Moose Trait to Add a Method to an Attribute ( Moose/Meta/Method/Accessor/Native/Array/apply.pm )
  • Download Code

Replies are listed 'Best First'.
Re^2: Moose Trait to Add a Method to an Attribute ( Moose/Meta/Method/Accessor/Native/Array/apply.pm )
by choroba (Cardinal) on Oct 08, 2016 at 09:20 UTC
    Thanks a lot! It's definitely a step in the right direction. But it modifies the Array trait globally, instead of creating a new one. _potential_value is not only confusing/disgusting, but also private and undocumented :-(

    I inspected some other methods in the same directory (e.g. map), which uses _return_value instead, but sort_in_place is much better because it shows how to modify the elements of the list. Thank again for pointing me to it. However, it still doesn't really modify the values in place: it returns a reference to a new anonymous array containing the new values.

    Update: I had to quotequote InvalidArgumentToMethod in the code, otherwise I got

    > Could not create writer for list because Failed to compile source: Bareword "InvalidArgumentToMethod" not allowed while "strict subs" in use at native delegation method My::apply_to_list (apply) of attribute list

    $self->_inline_throw_exception( '"InvalidArgumentToMethod"' => 'argument => $_[0],'. 'method_name => "apply",'. 'type_of_argument => "code reference",' +. 'type => "CodeRef",',

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,