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.

Другие вопросы по тегам