Хороший, плохой и уродливый лексический $_ в Perl 5.10+
Начиная с Perl 5.10, теперь можно лексически охватить контекстную переменную $_
, либо явно, как my $_;
, либо в конструкции given / when
.
Кто-нибудь нашел хорошее использование лексического $_
? Делает ли это какие-либо конструкции проще/безопаснее/быстрее?
Как насчет ситуаций, которые он усложняет? Лексический $_
вводит какие-либо ошибки в ваш код? (поскольку структуры управления, которые пишут $_
, будут использовать лексическую версию, если она есть в области видимости, это может изменить поведение кода, если оно содержит вызовы подпрограмм (из-за потери динамической области))
В конце концов, я хотел бы создать список, который разъясняет, когда использовать $_
как лексический, как глобальный, или когда это вообще не имеет значения.
NB: с perl5-5.24
эти экспериментальные функции больше не являются частью perl.
Ответы
Ответ 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.