digitalmars.D.learn - Switch with dynamic case
- Daniel Kozak (17/17) Feb 02 2016 import std.stdio;
- anonymous (58/75) Feb 02 2016 The key thing to understand is that the foreach is a "static" one. A
- Daniel Kozak (2/7) Feb 02 2016 Thanks :), this is all I need to know
import std.stdio; import std.typetuple : TypeTuple; alias cs = TypeTuple!(0, 1, 2, 3); void main(string[] argv) { switch(argv.length) { default: writeln("Uknown number of args"); break; foreach(c; cs) { case c: writefln("%s args", c); break; } } } This works, but I dont know why or how, is there some documentation about this feature?
Feb 02 2016
On 02.02.2016 15:07, Daniel Kozak wrote:import std.stdio; import std.typetuple : TypeTuple; alias cs = TypeTuple!(0, 1, 2, 3); void main(string[] argv) { switch(argv.length) { default: writeln("Uknown number of args"); break; foreach(c; cs) { case c: writefln("%s args", c); break; } } } This works, but I dont know why or how, is there some documentation about this feature?The key thing to understand is that the foreach is a "static" one. A static foreach is unrolled at compile-time. So that switch code is replaced at compile time with this, almost: ---- switch(argv.length) { default: writeln("Uknown number of args"); break; case 0: writefln("%s args", 0); break; case 1: writefln("%s args", 1); break; case 2: writefln("%s args", 0); break; } ---- "But", I hear you ask, "it breaks when I put the default at the bottom. What's up with that?". Yeah, that's a bit weird/buggy. The problem is with the break statement. It applies to the foreach, not to the switch. And while the foreach is unrolled at compile-time, the break is evaluated at run-time. The generated code really looks more like this: ---- switch(argv.length) { default: writeln("Uknown number of args"); break; /* start of unrolled foreach */ case 0: writefln("%s args", 0); goto behind_foreach; case 1: writefln("%s args", 1); goto behind_foreach; case 2: writefln("%s args", 0); goto behind_foreach; /* end of unrolled foreach */ behind_foreach: } ---- So, the breaks skip past the other cases that were created by the foreach, but they don't actually break out of the switch. There are at least two open issues related to this: https://issues.dlang.org/show_bug.cgi?id=14887 https://issues.dlang.org/show_bug.cgi?id=7835 Everything works fine when breaking the switch with a label: ---- sw: switch(argv.length) { foreach(c; cs) { case c: writefln("%s args", c); break sw; } default: writeln("Uknown number of args"); break; } ---- Unfortunately, the spec is rather quiet about static foreach. And you won't actually find the term "static foreach". The only thing I could find is a little "Foreach over Tuples" section on <https://dlang.org/spec/statement.html>, which doesn't tell a lot.
Feb 02 2016
On Tuesday, 2 February 2016 at 15:01:57 UTC, anonymous wrote:On 02.02.2016 15:07, Daniel Kozak wrote:Thanks :), this is all I need to know[...]The key thing to understand is that the foreach is a "static" one. A static foreach is unrolled at compile-time. [...]
Feb 02 2016