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

I'm trying to make a simple countdown timer to display at a console window (using 'sleep'), but the code below does something quite different from what I expect. I'm a Perl newbie (kinda) so I don't know if I must turn on some environmental variable to make it behave like I want.
#!/usr/bin/perl use warnings; use strict; sub countdown { my $int = $_[0]; while ($int > 0) { print "$int ... "; sleep 1; $int--; } print "\n"; } sub main { print "something happens in "; countdown (3); } &main;

Replies are listed 'Best First'.
Re: Trying to make a simple countdown timer
by jcb (Parson) on Aug 28, 2020 at 23:53 UTC

    I will guess that you are getting no output at all until the program ends and everything appears at once?

    Try inserting $| = 1; at line 4 and consult perlvar for what that means. :-)

      Ok good I think I overlooked how the printing to STDOUT is buffered by default, thanks for that. Problem solved. But I would only want the change of $| to 1 to affect that function, and when it exits I want $| back to default. Would this do that?
      sub countdown { local $| = 1; my $int = $_[0]; while ($int > 0) { print "$int ... "; sleep 1; $int--; } print "\n"; }
      *edit* just tried and seems to work as expected.
Re: Trying to make a simple countdown timer
by kcott (Archbishop) on Aug 29, 2020 at 00:51 UTC

    G'day maxamillionk,

    "... the code below does something quite different from what I expect."

    Without telling us what you expected to happen and what actually happened, we're left entirely with guesswork.

    This code runs for me. It does not produce any exception messages. It does what I'd expect it to do. I'm sort of making a point there: you have no idea what my exceptionsexpectations were. :-)

    Try adding another statement near the top (without changing anything else):

    ... use strict; $| = 1; ...

    Does that now do what you expect? If so, your problem was buffering. Depending inon your real requirements — beyond what you have in this tiny, demo script — there's possibly better ways to handle this: see "perlvar: $|", "IO::Handle" and "Suffering from Buffering?".

    For future reference, please read "How do I post a question effectively?" and (related but probably not particularly useful in this specific instance) "SSCCE".

    Nothing to do with the issue at hand; however, I thought I'd point out that &main is probably not what you want here. Unless you really want it, and know exactly why you want it, choose subname() over &subname. See perlsub for more about that.

    Update: Fixed typos:
    s/my exceptions/my expectations/ — thanks roboticus.
    s/Depending in/Depending on/ — noticed when fixing the previous typo.

    — Ken

Re: Trying to make a simple countdown timer
by Your Mother (Archbishop) on Aug 29, 2020 at 03:55 UTC

    It’s goofy but I use this in front of commands that I want a moment to reconsider whether or not I really meant to run it–

    perl -e '$|++; sleep 1 && printf "\r%2d...", $_ - 1 for reverse 1 .. 10; print $/'

    I think the order with the \r is actually “buggy” / “off-by-one” so if someone clever wants to revamp/improve. Dot, dot, dot. :P Anything longer than a minute these days Alexa and Siri got my back.