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

Hello Monks,

I'm currently in Perl training, as I wanted to review the basis, having learn Perl by taking over some advanced package without previous experience or course.

We just saw the 'continue' block for while and until, but the trainer couldn't find a good and short example of it. Do you have any light example to highlight its usage and usefulness ?

Thanks

  • Comment on use of 'continue' block for while/until

Replies are listed 'Best First'.
Re: use of 'continue' block for while/until
by Mutant (Priest) on Jun 11, 2008 at 08:19 UTC

    The docs are fairly self explanatory. The main use is if you have a 'next' statement in your main loop block, but you want something to happen after the 'next'. It just gives you an extra level of flow control in loops (see the docs for where each flow control statement will take you).

    Trivial example (but hopefully showing basic use):

    while ( my $foo = get_next_foo() ) { if ( $foo == 1 ) { next; } do_some_stuff(); } continue { # Everything ends up here whether 'next' was hit or not do_some_more_stuff(); }
    You can probably achieve the same thing with if statements, so (in this case at least) it's just syntactic suger.

      But sugar of a very sweet kind - it generally saves a level of indentation and avoids obfusification of logic flow.


      Perl is environmentally friendly - it saves trees
Re: use of 'continue' block for while/until
by ikegami (Patriarch) on Jun 11, 2008 at 07:50 UTC

    -p uses it to print the output at the end of every loop.

    >perl -MO=Deparse -pe1 LINE: while (defined($_ = <ARGV>)) { '???'; } continue { print $_; } -e syntax OK

    Another example is C-style for loops.
    for ($i=0; $i<10; ++$i) { foo }
    can be written as
    $i=0; while ($i<10) { foo } continue { ++$i }

Re: use of 'continue' block for while/until
by Limbic~Region (Chancellor) on Jun 11, 2008 at 13:19 UTC
    jeepj,
    I believe I have only used it once. Here is some code that does not use a continue block:
    my $counter = 0; while ($counter < $limit) { my $item = shift @work_queue; my $thingy = some_function($item); if ($thingy ne 'PARTY') { ++$counter; next; } # more code if $thingy ne 'PARTY' ++$counter; # thanks ikegami }

    Here is the same code with the continue block

    my $counter = 0; while ($counter < $limit) { my $item = shift @work_queue; my $thingy = some_function($item); next if $thingy ne 'PARTY'; # more code if $thingy ne 'PARTY' } continue { ++$counter; }

    Here is my general rule of thumb for when to use continue

    • You have 1 or more statements that need to be executed every single loop
    • You have more than one possible short-circuit condition in the loop

    It is a nice way of code re-use. Instead of doing

    if ($condition1) { # statement 1 # statement 2 # statement 3 next; } # more code if ($condition2) { # statement 1 # statement 2 # statement 3 next; }
    You can just do
    next if $condition1; # more code next if $condition2;

    Cheers - L~R

      Here is the same code with the continue block

      No. Those two snippets are different. The first only does ++$counter when $thingy ne 'PARTY'. The second does ++$counter unconditionally.

      my $limit = 3; my @work_queue = qw( a PARTY b c d); sub some_function { $_[0] } ... print(scalar(@work_queue), "\n");

      Prints 1 for the first snippet and 2 for the second.

        ikegami,
        You are quite correct. The problem was in my code, not my intention. The first should have had a ++$counter at the bottom of the loop. I will update that now.

        Cheers - L~R

Re: use of 'continue' block for while/until
by Jim (Curate) on Jun 11, 2008 at 16:49 UTC
    I most often use continue like this: I put the 'close ARGV if eof;' statement needed to reset $INPUT_LINE_NUMBER for each input filehandle (i.e., ARGV) in a continue block in the documented way:

    use strict; use warnings; use English qw( -no_match_vars ); RECORD: while (my $record = <>) { # Line number 1 is a header... if ($INPUT_LINE_NUMBER == 1) { # Per-file preprocessing goes here... next RECORD; # Skip to next record... } # Per-record processing goes here... } continue { close ARGV if eof; }
    Jim