Как используются функции lvalue в Perl?
-
21-08-2019 - |
Вопрос
Я не понимаю, для чего можно использовать функции lvalue?Чего я не могу сделать с помощью обычных подпрограмм?Не могли бы вы опубликовать несколько примеров?
Спасибо
Решение
Рекомендуется избегать значений 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).Я не думаю, что это так, но это достаточно двусмысленно, мне приходится проверять руководство, чтобы вспомнить, работает это или нет, и это плохо.
Другие советы
Вы можете использовать подпрограммы lvalue в качестве установщиков для членов объекта:
sub x : lvalue {
my $self = shift;
$self->{x};
}
Тогда позже:
$foo->x = 5;
Это сочетает в себе интуитивность установки элементов напрямую с гибкостью инкапсуляции метода установки на случай, если позже вы захотите изменить способ реализации объекта.Сравните со следующими более традиционными способами установки членов в Perl:
Интуитивный, но хрупкий;что, если вы измените способ реализации $foo?
$foo->{x} = 5;
Традиционный метод установки;не использует синтаксис присваивания для того, что представляет собой присваивание:
$foo->set_x(5);
Конечно, методы lvalue никогда по-настоящему не были приняты сообществом Perl, а использование подпрограмм lvalue является «странным», и все, что можно было бы получить для интуитивности, было бы потеряно из-за странности всего этого.
Они предоставляют другой интерфейс, который в некоторых случаях может быть более интуитивным.В отличие от традиционных сеттеров, вы можете изменить значение напрямую.Например
lvalue_sub($foo) =~ s/foo/bar/;
может быть чище, чем
my $tmp = some_sub($foo);
$tmp =~ s/foo/bar/;
some_sub($foo, $tmp);
Я не могу говорить об их частом использовании в моей обычной работе с 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.