Почему не выводится вывод ничего на каждой итерации цикла, когда я использую режим сна? - PullRequest
15 голосов
/ 02 июля 2011

Сегодня в моем колледже учитель задал мне вопрос.Он написал этот код на бумаге и сказал: «Каков будет выход этого кода?»

use warnings;

for (1 .. 20)
{
    print ".";
}

Я нашел это простым и сказал, что он будет зацикливаться 20 раз и на каждой итерации будет печатать точку(.) и, следовательно, всего будет 20 точек.

Он сказал, что вы правы, и затем он внес некоторые изменения в код.Код был:

use warnings;

for (1 .. 20)
{
    print ".";
    sleep 1;
}

Он сказал, что будет выходной сейчас?Я не знал о функции сна, я догадывался, что на каждой итерации она будет печатать точку (.), Затем она будет ждать 1 секунду (из-за функции сна), а затем снова будет повторяться, а затем снова будетнапечатайте (.), тогда он будет ждать 1 секунду и так далее ...

Учитель сказал мне проверить это дома.Я попробовал это дома и узнал, что второй код ждет 20 секунд, а затем он печатает все точки (20 точек) одновременно.Я хочу знать, как это случилось?Почему точка (.) Не печатается на каждой итерации?

Ответы [ 3 ]

24 голосов
/ 03 июля 2011

Реальная проблема не имеет ничего общего с sleep, а скорее с тем, что ............

Вы страдаете от буферизации . Приведенная ссылка приведет вас к отличной статье из журнала Perl Journal от 1998 года от Марка Джейсона Домина (автор Perl высшего порядка). Статье может быть более десяти лет, но эта тема сегодня так же актуальна, как и тогда, когда он ее написал.

Другие объяснили технику $| = 1;. Я хотел бы добавить к этим комментариям, что в доминирующем мышлении сообщества Perl кажется, что $| = 1 предпочтительнее, чем $|++ просто потому, что он более понятен по своему значению. Я знаю, что автоинкремент тоже довольно прост, но знает ли каждый, кто когда-либо будет смотреть на ваш код, поведение $| при применении ++ или -- (без поиска в perlvar ) , Я также предпочитаю локализовать любую модификацию «специальных переменных» Perl, чтобы эффекты не стирались в другие части кода, которые могут не очень хорошо сочетаться с определенным изменением поведения Perl по умолчанию. Поэтому в таком случае я бы написал:

use strict;
use warnings;

{
    local $| = 1;
    for ( 1 .. 20 ) {
        print '.';
        sleep 1;
    }
}
15 голосов
/ 02 июля 2011

Perl и многие другие программы, строковый буфер по умолчанию.Вы можете установить $| на 1, если вам нужен небуферизованный вывод.

12 голосов
/ 02 июля 2011

Не очищается буфер. Если в конце оператора print есть символ новой строки, он сделает это автоматически:

use warnings;

for (1 .. 20) {
    print ".\n";
    sleep 1;
}

Если вам не нужен перевод строки (я не думаю, что вы это делаете), вы можете использовать специальную переменную autoflush $|. Попробуйте установить значение 1 или увеличить его.

use warnings;

$|++;

for (1 .. 20) {
     print ".";
     sleep 1;
}
...