Perl, имеет некоторую специальную обработку для функции readline
(и эквивалентный оператор <>
I/O), где он рассматривает выражения
while (<HANDLE>)
while (readline(HANDLE))
как эквивалент
while (defined($_ = <HANDLE>))
ср
$ perl -MO=Deparse -e 'f($_) while <>'
f($_) while defined($_ = <ARGV>); <--- implicitly sets $_
-e syntax OK
Но это автоматическое назначение, кажется, не произойдет, если вы угнать readline
функции:
$ perl -MO=Deparse -e 'BEGIN {
> *CORE::GLOBAL::readline = sub { }
> }
> f($_) while <>'
sub BEGIN {
*CORE::GLOBAL::readline = sub {
};
}
f($_) while readline(ARGV); <--- doesn't set $_ !
-e syntax OK
Конечно, это сделает работу функции пользовательского readline
неправильно для многих унаследованного кода. Выход, если этот код "foo"
с блоком BEGIN и "bar"
без него, но я хочу, чтобы он был "BAR"
.
use warnings;
BEGIN { *CORE::GLOBAL::readline = \&uc_readline; }
sub uc_readline {
my $line = CORE::readline(shift || *ARGV);
return uc $line if defined $line;
return;
}
($_, $bar) = ("foo\n", "bar\n");
open X, '<', \$bar;
while (<X>) {
print $_; # want and expect to see "BAR\n"
}
Какие у меня есть варианты, чтобы угнать функцию readline
, но все-таки получить надлежащее лечение от while (<...>)
идиомы? Нецелесообразно явно преобразовывать все в while (defined($_=<...>))
во все устаревший код.
Причина здесь в том, что код, который делает это преобразование ('Perl_newLOOPOP', opmini.c: 5318) работает на optree и он ищет' OP_READLINE' - но если 'CORE :: GLOBAL :: readline' определяется при компиляции, вместо этого вместо него будет использоваться' OP_ENTERSUB' вместо этого, чтобы преобразование while никогда не происходило. Я не уверен, что это может быть ошибкой или нет :) – hobbs
Ух, я боялся, что это что-то в этом роде. Если это не ошибка, по крайней мере, это недокументировано. – mob
oops, похоже, я слишком долго ждал, чтобы сообщить вам, что я отправил его на perlbug - потому что вы тоже. Это нормально, вы дали тестовый пример :) – hobbs