Control flow

redo#

Restart the current iteration of a loop without re-testing the condition and without running the continue block.

redo jumps back to the top of the loop body and re-runs it on the same input — the conditional that guards the loop is not re-evaluated, $_ is not advanced by while (<FH>), the iterator of a foreach is not advanced, and any continue { } block attached to the loop is skipped. The current pass happens again from the beginning.

Synopsis#

redo
redo LABEL
redo EXPR

What you get back#

redo does not return a value. It is a flow-control operator: it transfers control and never falls through to the next statement. Do not try to use it as the value of an expression — in particular, it cannot be used to return a value from eval { }, sub { }, or do { }.

Which loop it targets#

With no argument, redo refers to the innermost enclosing loop. With a LABEL, it restarts the loop tagged with that label, allowing you to reach out of nested loops:

OUTER: while (...) {
    while (...) {
        redo OUTER;      # restart the while (...) above
    }
}

redo EXPR (added in Perl 5.18) computes the label at runtime. The expression must evaluate to a string naming a label currently in scope:

my $target = "OUTER";
redo $target;

A bare block counts as a loop that runs once, so redo inside a block turns it into a looping construct:

{
    my $line = <STDIN>;
    redo if $line =~ /^\s*$/;   # skip blank lines, re-read
    print $line;
}

redo vs next vs last#

All three take an optional LABEL and all three affect loop control, but they differ in what they skip:

  • last — exit the loop entirely. continue block is not run.

  • next — go to the next iteration. continue block is run, then the loop condition is re-tested.

  • redo — re-run the same iteration. continue block is not run, and the loop condition is not re-tested.

The continue-block difference is the one that catches people out. If a loop uses continue { } to increment a counter or advance a cursor, redo will not advance it — that’s the whole point, but it is also the whole foot-gun.

Examples#

Re-prompt until the user gives valid input. The continue block is skipped, so $attempts only counts completed iterations, which is usually what you want:

my $attempts = 0;
while (1) {
    print "Enter a positive integer: ";
    my $n = <STDIN>;
    chomp $n;
    redo unless $n =~ /^[0-9]+$/ && $n > 0;
    print "Got $n after $attempts rejected tries.\n";
    last;
} continue {
    $attempts++;
}

Restart processing of the current line after patching it — the classic “lie to yourself about what was just read” pattern, here stripping Pascal-style block comments that may span multiple input lines:

LINE: while (<STDIN>) {
    while (s|({.*}.*){.*}|$1 |) {}
    s|{.*}| |;
    if (s|{.*| |) {
        my $front = $_;
        while (<STDIN>) {
            if (/}/) {            # end of comment?
                s|^|$front\{|;
                redo LINE;        # re-process the patched line
            }
        }
    }
    print;
}

Target an outer loop by label. redo INNER would restart the inner loop on the current $x; redo OUTER restarts the outer loop on the current $x without advancing the foreach iterator:

OUTER: foreach my $x (@xs) {
    INNER: foreach my $y (@ys) {
        redo OUTER if should_restart($x, $y);
    }
}

Turn a bare block into a retry loop. Without redo this block runs exactly once; with redo it runs until the fetch succeeds:

my $tries = 0;
{
    my $ok = try_fetch();
    if (!$ok && ++$tries < 3) {
        sleep 1;
        redo;
    }
}

Edge cases#

  • continue is not run. This is the defining difference from next. If your loop relies on continue { } for counters, cursors, or cleanup, redo will bypass all of it. Either move the work into the body or use next instead.

  • Loop condition is not re-tested. while (cond) { ... redo; } will keep looping even if cond would now be false. You are responsible for ensuring the redo path eventually exits via last, return, or a conditional fall-through.

  • Easy infinite loop. redo with no state change is a tight infinite loop — typically not what you want. Always pair redo with a condition that eventually becomes false, or with a retry counter that triggers last.

  • foreach does not advance. foreach my $x (@xs) { redo } keeps $x pinned at the current element and loops on it forever. The iterator only advances on fall-through or next.

  • while (<FH>) does not read the next line. $_ retains the current line across the redo, which is precisely why the Pascal comment stripper above works.

  • redo out of grep / map is not supported. Upstream documents this as undefined; do not use redo to exit or restart a grep BLOCK LIST or map BLOCK LIST.

  • redo out of eval, sub, or do is not a return. It performs flow control; there is no value to return. A redo that would have to cross such a boundary to reach a loop is a runtime error (“Can’t redo outside a loop block”).

  • Precedence quirk. Unlike most named operators, redo has the precedence of assignment and is exempt from the looks-like-a-function rule. redo ("foo")."bar" passes the whole concatenation as the argument to redo — the parentheses do not isolate "foo".

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • last — exit the loop entirely; continue block is not run, same as redo

  • next — advance to the next iteration; continue block is run and the loop condition is re-tested

  • return — return from the enclosing subroutine, not just the loop; unlike redo, it yields a value

  • continue — the block that redo skips but next runs; the core of the three-way distinction