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

I just came across a piece of code that reduces to:

$n = 10; while( $n ){ print $n--; } continue{ sleep 1; }

Which as far as I can see is identical in behaviour to:

$n = 10; while( $n ){ print $n--; sleep 1 }

Is there any benefit to the first form?

I can't ever remember having used it. Do you? Could you post an example or two of its real world uses?


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
"I'd rather go naked than blow up my ass"

Replies are listed 'Best First'.
Re: while(){}continue{}; Useful?
by kennethk (Abbot) on Mar 03, 2010 at 16:27 UTC
    Were there nexts in the code? They would influence how the continue block got implemented. Consider

    my $n = 10; while( $n ){ print $n--; next if $n%2; } continue{ sleep 1; }

    vs.

    my $n = 10; while( $n ){ print $n--; next if $n%2; sleep 1; }

    I've never had to use flow control like this, but I can see that it could be theoretically useful.

      Hm. Seems to me that

      my $n = 10; while( $n ){ print $n--; next if $n%2; ## do other stuff here } continue{ sleep 1; }

      Is exactly equivalent to:

      my $n = 10; while( $n ){ print $n--; unless( $n%2 ) { ## do other stuff here } sleep 1; }

      And far clearer. (Even if you prefer the if( not $n%2 ) form.)

      There has to be a good use for it, I'm just not seeing it.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        I think the concept is handling complex branching with early return in the main body and exporting operations required every time. How about something more along the lines of:
        #!/usr/bin/perl use strict; use warnings; my @array = qw(1 2 cat dog 1.3 7.2); for (@array) { if (/\./) { $_*=2; next; } if (/\d/) { $_*=4; next; } } continue { print; }

        Of course TIMTOWTDI and I'm trying to come up with a contrived example.

      Another difficulty with this structure is that lexicals defined within the  while block are not available in the  continue block:

      >perl -wMstrict -le "my $n = 3; while ($n--) { my $i = $n * $n; } continue { print qq{n $n i $i}; } " Global symbol "$i" requires explicit package name at -e line 1. Execution of -e aborted due to compilation errors.

      I think Perl 6 addresses this through the  KEEP block (?) and related mechanisms.

      I, too, cannot remember ever using this structure explicitly, but have use it implicitly occasionally via the  -p command line switch.

Re: while(){}continue{}; Useful?
by ikegami (Patriarch) on Mar 03, 2010 at 18:14 UTC
    For an example usage, consider -p.
    $ perl -MO=Deparse -pe'f()' LINE: while (defined($_ = <ARGV>)) { f(); } continue { die "-p destination: $!\n" unless print $_; } -e syntax OK

    It's just a question of pref, I think. It's also has a parallel with for(;;). Scoping aside,

    for (A; B; C) { D; }
    is basically the same as
    A; while (B) { D; } continue { C; }
    I've never used continue.

      I use it a fair amount, mostly for your last example type situation, when the 'C' code is more complex than a single line. I find it easier to read to keep the 'loop maintenance' and 'loop actions' code separate.

      My most common example is probably a user-input loop: 'B' is while I can read from the input, and 'C' is the prompt/menu. (This assumes an interactive-only program, of course.) 'D' is the actual code to handle the different choices.

      Yes, that could be put in the loop in most/all cases, but I like knowing where to look for each type of code, and that they won't interfere with each other.

Re: while(){}continue{}; Useful?
by Argel (Prior) on Mar 03, 2010 at 22:06 UTC
    The Camel Book gives an example where you can increment a loop variable even when being interrupted by next (pg. 121):
    LINE: while (&lt;STDIN&gt;) { next LINE if /^#/; # skip comments next line if /^$/; # skip blank lines ... } continue { $count++; }
    So, yeah, it's not very useful, especially given the scope issue.

    Elda Taluta; Sarks Sark; Ark Arks

      > So, yeah, it's not very useful, especially given the scope issue.

      Why? You can still declare a variable in the head-clause!

      $\="\n"; while (my $x= < 1 2 3 4 >) { # using glob as iterator next if $x%2; print "$x: chacha" } continue { print "$x: rumba" } print $x;

      output

      1: rumba 2: chacha 2: rumba 3: rumba 4: chacha 4: rumba Use of uninitialized value $x in print at /home/lanx/tmp/continue.pl l +ine 8.

      it's treating blocks consistently, which is a big plus in Perl! 8)

      Cheers Rolf

        This produces identical results, and IMO is far clearer and more intuative:

        $\="\n"; while (my $x= < 1 2 3 4 >) { # using glob as iterator unless( $x%2 ) { print "$x: chacha" } print "$x: rumba" } print $x;

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        Yeah, the Camel Book also uses while and continue to show how a for loop works. But still, its use seems rather limited, which is probably why it isn't used that often (the Camel Book even acknowledges that it rarely sees use).

        Elda Taluta; Sarks Sark; Ark Arks