Каковы применения подпрограмм 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.