In Control flow§

See primary documentation in context for loop

The loop statement takes three statements in parentheses separated by ; that take the roles of initializer, conditional and incrementer, respectively. The initializer is executed once before the conditional is first tested. In case the initializer involves a variable declaration, the variable is declared as a lexical variable in the loop's outer or containing scope so that it can be used in code following the loop statement. The conditional is executed before each iteration and coerced to Bool; if False the loop is stopped. The incrementer is executed after each iteration, and before the conditional is tested again.

loop (my $i = 0$i < 10$i++{       # A typical loop 
    say $i;
}
 
my @str = "However Long".comb;          # Our very own .char routine: 
loop (my $l = 0;;) {                    # Declare $l in outer scope 
    last if !@str[$l++]                 # and count chars until we hit an 
}                                       # undefined element (Any) 
say "The string is {--$l} chars long.";

The infinite loop does not require parentheses.

loop { say 'forever' }

The loop statement may be used to produce values from the result of each run of the attached block if it appears in lists:

(loop ( my $i = 0$i++ < 3;) { $i * 2 }).say;               # OUTPUT: «(2 4 6)␤» 
my @a = (loop ( my $j = 0$j++ < 3;) { $j * 2 }); @a.say;   # OUTPUT: «[2 4 6]␤» 
my @b = do loop ( my $k = 0$k++ < 3;) { $k * 2 }@b.say;  # same thing

Unlike a for loop, one should not rely on whether returned values are produced lazily. It would probably be best to use eager to guarantee that a loop whose return value may be used actually runs:

sub heads-in-a-row {
    (eager loop (; 2.rand < 1;) { "heads".say })
}