I have a
package Test;
use Moose;
has 'attr' => ( is => 'rw', isa => 'Str' );
Inside a method I'd like to apply a s/pattern/string/g
on the attribute. For reasons documented in Moose (basically to properly support polymorphism) I do not want to access the $self->{attr}
directly, so a simple:
$self->{attr} =~ s/pattern/string/g;
is not an option. How can I do this efficiently in speed and little but clear code with Moose?
Options I came up with are:
1) Use a temporary variable, and the usual getter/setter method:
my $dummy = $self->attr;
$dummy =~ s/pattern/string/g;
$self->attr($dummy);
2) Using the attr getter/setter on the left hand side:
$self->attr($dummy) =~ s/pattern/string/g;
But this obviously throws an error
Can't modify non-lvalue subroutine call at Test.pm line 58, line 29
Is there a way to use Moose accessors as lvalue subs?
3) Use the String traits
Redefine the attribute:
has 'attr' => ( is => 'rw', isa => 'Str', traits => ['String'],
handles => { replace_attr => 'replace'} );
Then in the method use:
$self->replace_attr('pattern', 'string');
However the docs explicitly say, there's no way to specify the /g
flag.
Any elegant, simple, somewhat efficient method available out of the box?
I have used this approach in the past and I think it seems suitable to me for general use in terms of efficiency and cleanliness. It also works with the /g
modifier.
$self->attr( $self->attr =~ s/pattern/string/gr );
I suspect that under the hood this is the same as your first example with the temporary variable, it is just hidden from us.
Please note that the to use the /r
modifier, which returns the result of the substitution without modifying the original, requires Perl 5.14+.