Perl: Пожалуйста, объясните мне следующее поведение while()
1. Почему while (<$filehandle>)
итерация по файлу без всяких проблем, но она не выполняет итерацию по спискам или массивам без манипулирования самим массивом (например, использование while ($_ = shift @array){print $_}
? Как это произошло?
2. Как это while ($var = @array){print $var}
удается перебрать весь массив? не должны $var
просто получить количество показателей в @array
и вернуть это значение (так что создание бесконечного цикла)?
Из моего понимания while()
читает условие оператора и зацикливается, пока оно находит его верным. Что меня смущает, так это его поведение вокруг файловых дескрипторов, списков и тому подобного.
Пожалуйста, помогите мне понять больше о while()
поскольку я нахожу этого оператора очень запутанным иногда.
2 ответа
Давайте начнем с рассмотрения while(<$filehandle>)
, Это на самом деле сокращение Perl для этого:
while (defined($_ = <$filehandle>)) {
print $_;
}
Таким образом, каждый раз в цикле вы читаете следующую строку из файла, и если она не определена, вы выходите из цикла. Если оно определено, вы продолжите. Как вы ожидаете, while
будет зацикливаться, пока условие оценивается как истинное.
Вы сможете увидеть это, запустив perl -MO=Deparse program.pl
, Вы также можете ознакомиться с документацией в разделе Loop Control. Оператор diamond аналогичен readline подпрограммы (он читает следующую строку из файла).
В случае для while ($_ = shift @array){print $_}
, вы будете изменять массив, когда условие для while
цикл проверен. Сдвиг подпрограммы удаляет первый элемент массива и возвращает его. Так $_
будет установлен правильно, но ваш массив начнет терять элементы.
В следующем случае while ($var = @array){print $var}
, $var
будет равно количеству элементов в массиве. Это потому, что вы используете @array
в скалярном контексте. Это, скорее всего, будет оцениваться как истина, потому что от perlsyn
Число 0, строки "0" и "", пустой список () и undef - все ложно в логическом контексте. Все остальные значения верны.
Возьмите этот однострочный пример:
perl -le 'my @array = qw(a b c d e); my $var = @array; print $var'
Он напечатает номер 5
потому что в массиве 5 элементов. while
Цикл не будет выполняться, если в вашем массиве 0 элементов, и он застрянет в бесконечном цикле, если в нем 1 или более элементов.
Пример:
### This code will print 5 forever ###
my @array = qw(hi this is a test);
my $var;
while ( $var = @array ) {
print "$var\n";
}
На ваш вопрос 2 звучит так, как будто вы получаете разные результаты, но это застряло в цикле для меня.
Если вы собираетесь использовать Perl, вам придется освоиться с особыми случаями.
В первом случае особенным является оператор алмаза (<>).
Будьте осторожны с 2, поскольку это сломает ложные значения, IIRC.