Хорошие, плохие и уродливые лексические $ _ в Perl 5.10+ - PullRequest
19 голосов
/ 03 августа 2010

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

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

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

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


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

Ответы [ 4 ]

8 голосов
/ 04 августа 2010

IMO, одна из замечательных вещей, которую можно извлечь из лексики $_ - это новый _ символ-прототип.

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

Так что вместо того, чтобы писать:

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

    # Do stuff with $_
}

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

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

    # Do stuff with $_ or first arg.
}

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

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

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

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

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

3 голосов
/ 04 августа 2010

Однажды я обнаружил проблему (ошибка была бы слишком сильна), которая возникла, когда я играл с модулем 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 $_ является эффективным решением этой проблемы.

(модуль Inline был исправлен для исправления этой конкретной проблемы).

1 голос
/ 09 марта 2015

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

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


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

0 голосов
/ 04 августа 2010

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

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

...