On Friday, March 17, 2017 11:53:41 Michael via Digitalmars-d-learn wrote: > On Friday, 17 March 2017 at 11:30:48 UTC, Jonathan M Davis wrote: > > On Friday, March 17, 2017 01:55:19 Hussien via > > Digitalmars-d-learn wrote: > > > > I tend to agree with this. If the foreach is static, and > > continue and break are just going to be ignored, then they > > should just be illegal. Allowing them is just going to confuse > > people. Now, making it so that they actually work statically > > has some interesting possibilities, but that would fall apart > > as soon as you have any constructs that would use continue or > > break (e.g. a loop or switch statement) inside the static > > foreach, and it might break code in rare cases. So, we're > > probably better off just making them illegal. But having them > > be legal just seems disingenious, since they don't do anything. > > > > - Jonathan M Davis > > What exactly IS happening in the case of a continue in a > static-if? I could sort of imagine that maybe if you were > expecting the loop to be unrolled, that you then have a continue > statement in the correct part of the unrolled loop. But I take it > this isn't what's happening?
Okay. I completely misunderstood what was happening based on the previous posts. For instance, from this test import std.meta; import std.stdio; void main() { foreach(str; ["hello", "world", "foo", "bar"]) { foreach(i; AliasSeq!(0, 1, 2, 3, 4)) { static if(i / 2 == 0) writefln("%s: %s", i, str); else { writefln("%s: skipping %s", i, str); break; } } writeln(); } } it looks like break and continue _are_ used at compile time, since it prints 0: hello 1: hello 2: skipping hello 0: world 1: world 2: skipping world 0: foo 1: foo 2: skipping foo 0: bar 1: bar 2: skipping bar whereas if the break were just compiled in to be run at runtime, you never would have seen any of the strings past "hello" in the outer loop get printed. So, the issue is _not_ that continue and break are always treated as runtime constructs or outright ignored. And if we have import std.meta; import std.stdio; void main() { foreach(str; AliasSeq!("a", "b", "c")) { static if(str == "a") continue; writeln(str); } } it prints b c because when the loop is unrolled, wirteln isn't compiled in (and in fact, if you compile with -w, the code won't compile at all, because writeln is unreachable in the "a" iteration). On the other hand, if we have import std.meta; import std.stdio; void main() { foreach(str; AliasSeq!("a", "b", "c")) { static if(str == "a") continue; pragma(msg, str); } } then we get a b c which is what the OP was complaining about. Now, as to whether that's a bug or not, I don't know. pragma(msg, ...) prints whenever it's compiled, and as shown by the compilation error when you compile in the -w case, the code after the static if _is_ compiled in. It just ends up not being run. Certainly, the continue and break are _not_ skipped like I originally understood to be the case. So, that's not the bug. If there _is_ a bug, it's that the rest of the code in the loop after the static if is compiled after the continue, and I don't know that that is a bug. Remember that this is basically doing loop unrolling, which is not necessarily the same thing as you would expect from a "static foreach." It's not like we're building a string mixin here. It's more like the same code is being copy-pasted over and over but potentially with some tweaks on a given iteration. So, I'm not at all convinced that this is a bug, but I do agree that the semantics are a bit wonky. Regardless, based on what happens with the writeln case, it's clearly the case that you should be using an else branch if you want to cleanly use a continue in a foreach like this. - Jonathan M Davis