3

I'm starting to learn perl, using the Wrox Beginning Perl available on perl.org and have a question regarding a for loop example they provide in Chapter 3.

#!/usr/bin/perl

use warnings;
use strict;

my @count = (1..10);
for (reverse(@count)) {
        print "$_...\n";
        sleep 1;
}
print "Blast Off!\n"

This is the script they provide, and it works as expected. It displays a number followed by ... every second, waiting a second in between each number. When done, it displays Blast Off!

However if I remove the newline from the print statement, the behaviour changes. The script silently waits 10 seconds and then displays all 10 numbers and Blash Off! at once. Why the change?

#!/usr/bin/perl

use warnings;
use strict;

my @count = (1..10);
for (reverse(@count)) {
        print "$_...";
        sleep 1;
}
print "Blast Off!\n"
Menachem
  • 173
  • 8

4 Answers4

11

Perl is buffering the print output and the buffer isn't flushed until the newline. Alternatively, you can add $| = 1 before your loop to tell Perl to flush the buffer between the print statements, thus giving you the expected output with the proper delay:

#!/usr/bin/perl

use warnings;
use strict;

$| = 1; #Add this line
my @count = (1..10);
for (reverse(@count)) {
        print "$_...";
        sleep 1;
}
print "Blast Off!\n"'
eldarerathis
  • 35,455
  • 10
  • 90
  • 93
4

Standard output is line buffered. It won't flush the buffer until it sees a newline. You can correct this by adding the following line before the loop:

my $ofh = select(STDOUT); $| = 1; select $ofh;

Let's break that down:

my $ofh = select(STDOUT); - selects the STDOUT (standard output) as the current selected file handle, and stores whatever was the previous selected file handle in $ofh

$| = 1; - sets the current file handle (ie. STDOUT) to unbuffered.

select $ofh; - reselects whatever was the selected file handle before, so that if the code had selected a file handle other than STDOUT at some point, it will still be selected after this line of code is finished.

Paul Tomblin
  • 179,021
  • 58
  • 319
  • 408
4

You are looking at the standard behavior of the line-oriented output of the C stdio library when writing to a terminal.

See autoflush for perl details.

msw
  • 42,753
  • 9
  • 87
  • 112
1

A neater way than using select() to set the autoflush flag on STDOUT is to use IO::Handle (which has been included with the Perl core since version 5.004):

use IO::Handle;
STDOUT->autoflush(1)
ilmari
  • 301
  • 1
  • 3