2015-09-22 2 views
4

У меня естьКак эффективно применять замену регулярных выражений по атрибуту Moose?

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

Внутри метода я хотел бы применить s/pattern/string/g на атрибут. По причинам, документированных в Мус (в основном правильно поддерживать полиморфизм) Я не хочу, чтобы получить доступ к $self->{attr} непосредственно, так просто:

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

не вариант. Как я могу сделать это эффективно в скорости и небольшом, но понятном коде с Moose?

Опции я придумал являются:

1) С помощью временной переменной, а обычный метод геттер/сеттер:

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

2) Использование атр геттер/сеттер на левой стороне :

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

Но это, очевидно, выдает ошибку

Невозможно изменить без Lvalue вызова подпрограммы на 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 флаг.

Любой элегантный, простой, несколько эффективный метод, доступный из коробки?

+0

Связанный: [Правильный способ использования атрибута класса Moose в регулярном выражении?] (Http://stackoverflow.com/q/32613115/176646) – ThisSuitIsBlackNot

+0

Зачем вы хотите это сделать? Может быть, реализовать его как модификатор 'around' для автора или как триггер, имеет больше смысла, чем его где-то еще? – simbabque

+0

Если аксессор был подмножеством lvalue, он мог бы эффективно получить доступ к '$ self -> {attr}' непосредственно, если не были созданы магические значения возврата, замедляя каждый доступ к каждому доступному ему не нужно. – ikegami

ответ

5

Я использовал этот подход в прошлом, и я думаю, что он мне подходит для общего использования с точки зрения эффективности и чистоты. Он также работает с модификатором /g.

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

Я подозреваю, что под капотом это то же самое, как ваш первый пример с временной переменной, она просто скрыта от нас.

Обратите внимание, что для использования модификатора /r, возвращающего результат подстановки без изменения оригинала, требуется Perl 5.14+.

+0

Это короче моих попыток, и, следовательно, хорошее предложение. Если бы мы могли избежать избыточности кода, это было бы хорошо. – cfi

+0

Несмотря на то, что я пошел с моим собственным ответом в качестве решения, и хотя я и не сделал (и в настоящее время не буду) делать тест производительности, я отмечаю ваше решение как решение, потому что это не разумная идея заплатить штраф за исполнение каждый доступ, когда все, что мы получаем, - это немного меньше избыточности кодирования. Хотя я решительно выступаю против такой избыточности, этот очень локальный (два имени attr рядом друг с другом и хорошо поддерживаемые. – cfi

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::Magic и функцию perlsub lvalue, так что есть накладные расходы на производительность для этого подхода, который влияет на каждый доступ к атрибуту «traited», а не только на те, где он используется как левая сторона. Спасибо LeoNerd и ikegami за их корректирующие комментарии к моим предыдущим заявлениям.

Поэтому, подтвержденный документацией модуля, проверка типа Moose по-прежнему работает, и запускаются триггеры.

+0

Ум, это так? При последнем чтении сейчас (версия 0.981) утверждается, что все проверки и триггеры работают просто – LeoNerd

+0

@LeoNerd прав. Он возвращает волшебный скаляр вместо того, чтобы возвращать '$ self -> {attr}' непосредственно, чтобы правильно делать такие вещи, как проверка типов. Я считаю, что это значительно увеличивает стоимость доступа к атрибуту. – ikegami

+0

@LeoNerd и ikegami: Какая грубая ошибка: я прочитал документы и написал обратное. Спасибо, что исправил меня, я обновил ответ. – cfi

Смежные вопросы