Tuesday, March 9, 2010

Perl: Ошибка "Modification of a read-only value attempted" в цикле while

Конструкция while (<FH>) {...} в Perl имеет замечательную особенность: затирать глобальную переменную $_. Все прочие конструкции языка, которые неявно присваивают какие-то значения $_, предварительно ее локализуют (foreach, map, grep). Однако, в случае с while этого не происходит. При этом, если $_ ссылается на константное значение, выдается ошибка:
my %val = map { $_ => read_val($_) } (1..3);

sub read_val {
open my $fh, '<', 'myfile' or die $!;
while (<$fh>) {
return $_ if $. == $_[0];
}
}

Modification of a read-only value attempted at ...

Это поведение документировано в perlop:
If and only if the input symbol is the only thing inside the conditional of a while statement ..., the value is automatically assigned to the global variable $_, destroying whatever was there previously. ... The $_ variable is not implicitly localized. You'll have to put a local $_; before the loop if you want that to happen.


Таким образом, while (<FH>) эквивалентно while (defined($_ = <FH>)). Этим и объясняется ошибка в примере.

No comments:

Post a Comment