Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I've been trying to create a simple countdown in perl, using the following code.
while ($num) { print "$num\r"; $num--; sleep 1; }
However, the script counts all the way down without printing the countdown as expected. When I substituted "a" in for "$num\r", it waited until the countdown was done (4 seconds in the test), then printed "aaaa", as opposed to printing "a", waiting a second, printing "a", etc. Any suggestions on how to make this work? Thanks.

Replies are listed 'Best First'.
Re: Perl only prints complete lines?
by ikegami (Patriarch) on May 05, 2008 at 09:17 UTC
    You are suffering from buffering.
    use IO::Handle; STDOUT->autoflush(1); while ($num) { print "$num\r"; $num--; sleep 1; }
    or
    use IO::Handle; while ($num) { print "$num\r"; STDOUT->flush(); $num--; sleep 1; }
Re: Perl only prints complete lines?
by CountZero (Bishop) on May 05, 2008 at 10:23 UTC
    A good practice (some would say, the best practice) is to limit any changes to global variables which control Perl's behaviour to as small a scope as possible, by using local $| = 1 within the scope you need it.

    Of course for your small program, it really does not matter but once you use external modules whose behaviour may or may not be influenced by your twiggling of Perl's magickal variables, you should think twice.

    This goes even more if you write modules or sub-routines yourself. You really do not want to export these changes beyond these modules or sub-routines.

    Suppose you have written a nice logging-to-disk routine/module and you wish to make sure all lines come out as quick as possible in the right order, so you globally autoflush your print to the log file. If someone else uses your module and he writes to disk a huge number of very short lines (say only a few bytes each), then each write would be done separately which will slow down his program to a crawl and he will blame Perl for being such a slow language; never suspecting that his use of your logging-module is the culprit. Limiting your autoflush to your own sub-routine/module would avoid such thing from happening.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Perl only prints complete lines?
by moritz (Cardinal) on May 05, 2008 at 09:18 UTC
    You're hit by line buffering of STDOUT. Try $| = 1 before the loop.
Re: Perl only prints complete lines?
by FunkyMonk (Bishop) on May 05, 2008 at 09:19 UTC
    You need to turn on autoflushing with $| = 1;. See perlvar

    Unless I state otherwise, all my code runs with strict and warnings
Re: Perl only prints complete lines?
by Anonymous Monk on May 05, 2008 at 18:08 UTC
    Thanks for all the replies. I used 'local $| = 1;', and it worked perfectly. Thanks.