Подтвердить что ты не робот

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

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

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

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

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


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

4b9b3361

Ответ 1

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

Ответ 2

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

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 был исправлен, чтобы исправить эту проблему).

Ответ 3

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

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


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

Ответ 4

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

Я протестировал код против различных версий perl 5,8 и 5,10, в то время как с 5,6 описанием Camel для случайных ссылок. Не было никаких проблем. Большинство моих вещей было первоначально сделано для perl 5.8.8.