Хорошие, плохие и уродливые лексические $_ в 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.