Хорошие, плохие и уродливые лексические $_ в Perl 5.10+

Начиная с Perl 5.10, теперь можно лексически изменять контекстную переменную $_ либо явно как my $_; или в given / when построить.

Кто-нибудь нашел хорошее использование лексического $_? Делает ли это какие-либо конструкции проще / безопаснее / быстрее?

А как насчет ситуаций, которые это усложняет? Имеет лексический $_ внесены какие-либо ошибки в ваш код? (так как управляющие структуры, которые пишут в $_ будет использовать лексическую версию, если она находится в области видимости, это может изменить поведение кода, если он содержит какие-либо вызовы подпрограммы (из-за потери динамической области видимости))

В конце я хотел бы создать список, который разъясняет, когда использовать $_ как лексический, как глобальный, или когда это вообще не имеет значения.


NB: по состоянию на perl5-5.24 Эти экспериментальные функции больше не являются частью Perl.

4 ответа

Решение

ИМО, одна отличная вещь, чтобы выйти из лексического $_ это новый _ символ прототипа.

Это позволяет вам указать подпрограмму так, чтобы она заняла один скаляр или, если ничего не будет предоставлено, она получит $_,

Поэтому вместо того, чтобы писать:

sub foo {
    my $arg = @_ ? shift : $_;

    # Do stuff with $_
}

Я могу написать:

sub foo(_) {
    my $arg = shift;

    # Do stuff with $_ or first arg.
}

Не большое изменение, но это намного проще, когда я хочу такое поведение. Удаление Boilerplate это хорошая вещь.

Конечно, это влияет на изменение прототипов нескольких встроенных программ (например, chr), что может привести к поломке кода.

В целом приветствую лексический $_, Это дает мне инструмент, который я могу использовать, чтобы ограничить случайное копирование данных и странное взаимодействие между функциями. Если я решу использовать $_ в теле функции, лексизируя ее, я могу быть уверен, что любой код, который я вызываю, $_ не будет изменен в вызывающем коде.

Динамический охват интересен, но по большей части я хочу лексическую область видимости. Добавьте к этому осложнения вокруг $_, Я слышал страшные предупреждения о нецелесообразности просто делать local $_;- что лучше всего использовать for ( $foo ) { } вместо. Lexicalized $_ дает мне то, что я хочу, 99 раз из 100, когда я локализовал $_ любыми средствами. лексический $_ делает удобство и удобство чтения более надежным.

Большая часть моей работы была связана с Perl 5.8, поэтому я не имел удовольствия играть с лексическим $_ в более крупных проектах. Тем не менее, кажется, что это будет иметь большое значение для использования $_ безопаснее, что хорошо.

Однажды я обнаружил проблему (ошибка будет слишком сильным словом), которая возникла, когда я играл с Inline модуль. Этот простой скрипт:

use strict qw(vars subs);
for ('function') {
    $_->();
}
sub function {
  require Inline;
  Inline->bind(C => <<'__CODE__');
void foo() 
{
}
__CODE__
}

терпит неудачу с Modification of a read-only value attempted at /usr/lib/perl5/site_perl/5.10/Inline/C.pm line 380. сообщение об ошибке. Глубоко во внутренностях Inline Модуль это подпрограмма, которую хотел изменить $_, что приводит к сообщению об ошибке выше.

С помощью

for my $_ ('function') { ...

или иным образом объявив my $_ является жизнеспособным решением этой проблемы.

(The Inline модуль был исправлен, чтобы исправить эту конкретную проблему).

[ Обоснование: краткий дополнительный ответ с краткой сводкой для новичков в Perl, которые могут проходить мимо. При поиске "лексической темы perl" здесь можно оказаться здесь.]

К настоящему времени (2015) я полагаю, что общеизвестно, что введение лексической темы (my $_ и некоторые связанные особенности) привели к тому, что с самого начала было трудно обнаружить непреднамеренное поведение, поэтому оно было помечено как экспериментальное и затем вступило в стадию устаревания.


Частичное резюме #RT119315: Одно предложение было для чего-то вроде use feature 'lextopic'; чтобы использовать новую лексическую переменную темы: $^_, Другое замечание было то, что " неявное имя для оператора актуализации... кроме $_ "будет работать лучше всего в сочетании с явно лексическими функциями (например, лексическими map или же lmap). Будут ли эти подходы каким-то образом позволять given/when непонятно. В загробной жизни экспериментальной и амортизационной фаз, возможно, что-то может в конечном итоге жить в реке CPAN.

У меня здесь не было никаких проблем, хотя я склонен придерживаться политики "Не спрашивай, не говори", когда дело касается магии Перлза. Т.е. рутины, как правило, не ожидают, что их коллеги будут использовать нелексические данные в качестве побочного эффекта или не позволят им.

Я тестировал код на различных версиях Perl 5.8 и 5.10, в то же время используя 5.6, описывающий Camel для случайных ссылок. У меня не было проблем. Большинство моих работ изначально было сделано для Perl 5.8.8.

Другие вопросы по тегам