On 1/9/18 11:35 AM, H. S. Teoh wrote:
On Tue, Jan 09, 2018 at 10:57:03AM -0500, Steven Schveighoffer via 
Digitalmars-d-learn wrote:
I may have been misleading when I made my first comment. What I mean
is that you *can't* break or continue a static foreach, even with
labels. However, you *can* do it to a standard foreach over a tuple.
This may be one reason you want to use a tuple-foreach over a static
foreach.
[...]

Actually, that's wrong too. Tuple-foreach does not interpret
break/continue either. Here's a proof:

        alias Seq(A...) = A;
        foreach (i; Seq!(0, 1, 2, 3)) {
                static if (i==2)
                        break;
                static assert(i < 3); // will fail on the 4th iteration
        }

What actually happens is that all iterations are unrolled, then the
unreachable iterations are elided by the optimizer during codegen. The
foreach itself is not affected by break/continue at all.

A break or continue is simply a goto underneath. A goto in an unrolled loop isn't much different than a goto in a um... rolled loop :) It's just that there are copies of each loop body, and the gotos need copies of the labels.

So no, it's not "interpreted" by the foreach statement, but the foreach statement provides the anchors for the goto label targets.

e.g.:

int x;

foreach(i; Seq!(0, 1, 2, 3)) {
   x += i;
   static if(i % 2) continue;
   x *= i;
}

=>

int x;
{
   x += 0;
   x *= 0;
}
{
   x += 1;
   goto label1;
   x *= 1;
}
{
label1:
   x += 2;
   x *= 2;
}
{
   x += 3;
   goto label2;
   x *= 3;
}
label2:

And then of course, the optimizer weeds out the unreachable statements. Doing this with static foreach wouldn't be as pleasant. You'd have to branch the entire loop body, or use a goto in the case of a break.

-Steve

Reply via email to