如何在Moose属性上有效地应用正则表达式替换?

时间:2015-09-22 14:40:12

标签: perl attributes moose

我有一个

package Test;
use Moose;
has 'attr' => ( is => 'rw', isa => 'Str' );

在方法中,我想在属性上应用s/pattern/string/g。由于Moose中记录的原因(基本上是为了正确支持多态)我不想直接访问$self->{attr},所以很简单:

$self->{attr} =~ s/pattern/string/g;

不是一种选择。如何使用Moose在速度和清晰的代码中有效地完成这项工作?

我提出的选项是:

1)使用临时变量和通常的getter / setter方法:

my $dummy = $self->attr;
$dummy =~ s/pattern/string/g;
$self->attr($dummy);

2)使用左侧的attr getter / setter:

$self->attr($dummy) =~ s/pattern/string/g;

但这显然会引发错误

  

无法在Test.pm中修改非左值子程序调用   第58行,第29行

有没有办法将Moose访问器用作lvalue subs

3)使用String traits

重新定义属性:

has 'attr' => ( is => 'rw', isa => 'Str', traits  => ['String'],
                handles => { replace_attr => 'replace'}  );

然后在方法中使用:

$self->replace_attr('pattern', 'string');

然而,文档明确指出,没有办法指定/g标志。

开箱即用的任何优雅,简单,有效的方法?

2 个答案:

答案 0 :(得分:5)

我过去曾使用过这种方法,我认为在效率和清洁度方面似乎适合我。它也适用于/g修饰符。

$self->attr( $self->attr =~ s/pattern/string/gr );

我怀疑在引擎盖下这与你的第一个临时变量示例相同,它只是对我们隐藏。

请注意,要使用/r修饰符,它会在不修改原始内容的情况下返回替换结果,但需要使用Perl 5.14+。

答案 1 :(得分:4)

我的选项(2)和this question提供了使用MooseX::LvalueAttributes的想法:

package Test;
use Moose;
use MooseX::LvalueAttribute 'lvalue';
has 'attr' => ( is => 'rw', isa => 'Str', traits => [lvalue] );

这允许直截了当的语法:

$self->attr($dummy) =~ s/pattern/string/g;

在内部,它使用Variable::Magicperlsub lvalue功能,因此这种方法会产生性能开销,影响对“特定”网络的每次访问权限。属性,而不仅仅是它用作左手边的属性。感谢LeoNerd和ikegami对我之前的陈述的更正评论。

因此,并且在模块的文档中证实,Moose的类型检查仍然有效并触发了触发器。