Каковы применения подпрограмм lvalue в Perl?
Я не понимаю, какие могут быть применения lvalue-подпрограмм? Что я не могу выполнить с помощью обычных подпрограмм? Не могли бы вы привести несколько примеров?
Спасибо
Ответы
Ответ 1
Рекомендуется избегать LValues. Они забавные и все, но они путают новых пользователей, которые делают предположения о том, как работают все подмастеры, и поэтому их следует избегать в коде, когда доступен лучший способ.
Иногда бывает очень полезно использовать результат LValue для выполнения грязной работы.
substr( $string, $start, $stop ) = 'somevalue' # replaces the specified part of the substring.
Однако это также делает то же самое:
substr( $string, $start, $stop , 'somevalue' );
Разница здесь в основном в первом имеет значительно более выразительную силу, поскольку она делегирует поведение коду, который использует его вместо самой функции.
Например:
substr( $string, $start, $stop ) =~ s/a/b/g
Требуется выполнить
my $x = substr( $string, $start, $stop );
$x =~ s/a/b/g/;
substr( $string, $start, $stop, $x );
Это немного неприятно.
Несмотря на то, что здесь есть что-то неприятное, потому что вам нужно подумать о том, выполняет ли эта подстановка или нет с помощью $x ретроактивно, чтобы изменить строку или нет (из-за того, что substr является подпрограммой LValue). Я не думаю, что это так, но его достаточно двусмысленно, я должен проверить руководство, чтобы помнить, работает оно или нет, и что плохо.
Ответ 2
Вы можете использовать lvalue subs как сеттеры для членов объекта:
sub x : lvalue {
my $self = shift;
$self->{x};
}
Затем позже:
$foo->x = 5;
Это сочетает в себе интуитивность установки членов напрямую с гибкостью инкапсуляции сеттера, если вы позже захотите изменить способ реализации объекта. Сравните следующие традиционные способы установки элементов в Perl:
Интуитивный, но хрупкий; что, если вы измените способ реализации $foo?
$foo->{x} = 5;
Традиционный метод setter; не использует синтаксис присваивания для значений, которые присваиваются:
$foo->set_x(5);
Конечно, методы lvalue никогда не были охвачены сообществом Perl, а использование lvalue subs "странно", и все, что было бы получено для интуитивности, было бы потеряно из-за странности всего этого.
Ответ 3
Они предоставляют другой интерфейс, который в некоторых случаях может быть более интуитивным. В отличие от традиционных сеттеров, вы можете фактически изменить значение напрямую. Например
lvalue_sub($foo) =~ s/foo/bar/;
может быть чище, чем
my $tmp = some_sub($foo);
$tmp =~ s/foo/bar/;
some_sub($foo, $tmp);
Ответ 4
Я не могу говорить о том, чтобы использовать их в моем обычном Perl-материале, но они широко используются на языке данных Perl, когда вы принимаете фрагменты или другие подразделы. Например:
my $a = sequence(100);
# use lvalue in this increment:
$a->where($a < 10)++;
# Zero-out the last four elements
# notice the use of the overloaded .= operator:
$a->slice("-10:") .= 0;
Как и многие вещи в Perl, эта функция не используется во всей экосистеме, но ее использование по крайней мере в этой нише облегчает жизнь пользователям PDL.