digitalmars.D - A safer switch?
- bearophile (66/66) Oct 12 2009 This is a pruned method from a command-line Java program:
- Justin Johansson (31/46) Oct 12 2009 (Sorry bearophile, don't mean to steal your thunder but since I'm writin...
- bearophile (25/37) Oct 12 2009 That's a special case, with the purpose of shortening code a little. So ...
- Jeremie Pelletier (3/49) Oct 12 2009 final switch(color) { ... }
- language_fan (2/5) Oct 12 2009 Yes. Java does this.
- Justin Johansson (15/45) Oct 12 2009 My question written in haste.
- Ellery Newcomer (18/55) Oct 12 2009 I bet if you modified parse.c to translate
- Vladimir Panteleev (11/12) Oct 12 2009 (snip)
- Jarrett Billingsley (4/9) Oct 12 2009 "goto case;" already exists and jumps to the next case in the switch.
- Adam D. Ruppe (11/12) Oct 12 2009 This has been discussed to death *multiple times*. Why bring it up again...
- grauzone (16/36) Oct 12 2009 You can do something like this:
- Andrei Alexandrescu (9/50) Oct 12 2009 import std.getopt;
- Kagamin (2/14) Oct 13 2009 What's even better, modern D style allows you to work around some misdes...
This is a pruned method from a command-line Java program: private static void parseCmdLine(String args[]) { int i = 0; String arg; while (i < args.length && args[i].startsWith("-")) { arg = args[i++]; if (arg.equals("-s")) { if (i < args.length) size = new Integer(args[i++]).intValue(); else throw new Error("-l ..."); } else if (arg.equals("-m")) { printMsgs = true; } else if (arg.equals("-p")) { printResults = true; } else if (arg.equals("-h")) { usage(); } } if (size == 0) usage(); } I may translate part of that to D like this: switch (arg) { case "-s": if (idx < args.length) size = toInt(args[idx++]); else throw new Exception("..."); break; case "-m": printMessages = true; break; case "-p": printResults = true; break; case "-h": showUsage(); default: showUsage(); throw new Exception("..."); } (in most cases) that common bug. D may use some like this: switch (arg) { case("-s") { try { next_arg = iargs.next(); size = toInt(args[idx++]); } catch (...) { throw new Exception("..."); } } case("-m") { printMessages = true; } case("-p") // just 1 istruction, no {} needed printResults = true; case("-h"); // semicolon isn't allowed here showUsage(); default { // default case may need some care throw new Exception("..."); } } Mixing "case:" and "case()" in the same switch is not allowed, to keep things tidy. "break" is implicit. You can add "continue" if you want to step to the following case. If you put the switch inside a loop, the continue is relative to the switch and not the loop. So if you want to continue the loop you need a "continue LABEL;" where the LABEL if before the loop. Bye, bearophile
Oct 12 2009
bearophile Wrote:This is a pruned method from a command-line Java program: private static void parseCmdLine(String args[]) { ... } I may translate part of that to D like this: switch (arg) { ... } (in most cases) that common bug. D may use some like this: ...(Sorry bearophile, don't mean to steal your thunder but since I'm writing some D1 switch code right now, I may as well strike while the iron is still hot ...) Speaking of switch statements, when switching on an enum type, e.g. enum Color { RED, GREEN, BLUE } void foo( Color color) { switch (color) { case Color.RED: break; case Color.GREEN: break; case Color.BLUE: break; } } Would it be possible for the compiler to infer the declared enum type, in this case Color, making for abbreviation of the enum member names in the case clauses as per the following? void bar( Color color) { switch (color) { case RED: break; case GREEN: break; case BLUE: break; } } Koala hugs, -- Justin Johansson
Oct 12 2009
Justin Johansson:Would it be possible for the compiler to infer the declared enum type, in this case Color, making for abbreviation of the enum member names in the case clauses as per the following? void bar( Color color) { switch (color) { case RED: break; case GREEN: break; case BLUE: break; } }That's a special case, with the purpose of shortening code a little. So while writing Color.something isn't handy, it safe and it has no special casing. So I don't like your idea a lot. Related: I have compiled your code with D1 with warnings (-w): enum Color { RED, GREEN, BLUE } void foo(Color color) { switch (color) { case Color.RED: break; case Color.GREEN: break; case Color.BLUE: break; } } void main() {} It prints: warning - test.d(8): Error: switch statement has no default warning - test.d(8): Error: statement is not reachable But there's no need for default there because all enum cases are covered. So that warning test has to be improved. Bye, bearophile
Oct 12 2009
bearophile wrote:Justin Johansson:final switch(color) { ... } :)Would it be possible for the compiler to infer the declared enum type, in this case Color, making for abbreviation of the enum member names in the case clauses as per the following? void bar( Color color) { switch (color) { case RED: break; case GREEN: break; case BLUE: break; } }That's a special case, with the purpose of shortening code a little. So while writing Color.something isn't handy, it safe and it has no special casing. So I don't like your idea a lot. Related: I have compiled your code with D1 with warnings (-w): enum Color { RED, GREEN, BLUE } void foo(Color color) { switch (color) { case Color.RED: break; case Color.GREEN: break; case Color.BLUE: break; } } void main() {} It prints: warning - test.d(8): Error: switch statement has no default warning - test.d(8): Error: statement is not reachable But there's no need for default there because all enum cases are covered. So that warning test has to be improved. Bye, bearophile
Oct 12 2009
Mon, 12 Oct 2009 04:55:07 -0400, Justin Johansson thusly wrote:Would it be possible for the compiler to infer the declared enum type, in this case Color, making for abbreviation of the enum member names in the case clauses [snip]?Yes. Java does this.
Oct 12 2009
language_fan Wrote:Mon, 12 Oct 2009 04:55:07 -0400, Justin Johansson thusly wrote:My question written in haste. Strike "possible for the compiler to infer the declared enum type" and replace with "a desirable feature for the compiler to be able to infer the declared enum type". Naturally it would be possible. bearophile Wrote:Would it be possible for the compiler to infer the declared enum type, in this case Color, making for abbreviation of the enum member names in the case clauses [snip]?Yes. Java does this.That's a special case, with the purpose of shortening code a little. So while writing Color.something isn't handy, it safe and it has no special casing. So I don't like your idea a lot.Sorry; my feeling is that if it's not necessary to type the extra verbage, why be compelled to do so, especially in this case when the type of the case targets are tightly bound to the type of the var in the switch(). There is absolutely no loss of type safety that I can see .. though I'm prepared to be corrected. btw. It's been a few months since I've coded in Java but the reason the issue stuck me was that I had initially typed the shorter version in D out of die-hard (Java) habit and then, upon complaint, briefly thought, okay Mr D Compiler, since you insist ...Related: I have compiled your code with D1 with warnings (-w): enum Color { RED, GREEN, BLUE } void foo(Color color) { switch (color) { case Color.RED: break; case Color.GREEN: break; case Color.BLUE: break; } } warning - test.d(8): Error: switch statement has no default warning - test.d(8): Error: statement is not reachable But there's no need for default there because all enum cases are covered. So that warning test has to be improved.Indeed. -- Justin Johansson
Oct 12 2009
Justin Johansson wrote:Speaking of switch statements, when switching on an enum type, e.g. enum Color { RED, GREEN, BLUE } void foo( Color color) { switch (color) { case Color.RED: break; case Color.GREEN: break; case Color.BLUE: break; } } Would it be possible for the compiler to infer the declared enum type, in this case Color, making for abbreviation of the enum member names in the case clauses as per the following? void bar( Color color) { switch (color) { case RED: break; case GREEN: break; case BLUE: break; } } Koala hugs, -- Justin JohanssonI bet if you modified parse.c to translate switch(x){ ... case Exp: ... } to switch(x){ ... static if(is(typeof(x) == enum)){ with(typeof(x)){case Exp:}} else {case Exp:} ... } you could have your cake. Can anyone see any potential problems with this (other than symbol shadowing)? Pipsissewa hugs
Oct 12 2009
On Mon, 12 Oct 2009 11:03:13 +0300, bearophile <bearophileHUGS lycos.com> wrote:This is a pruned method from a command-line Java program:(snip) This was discussed before. IIRC, someone suggested to force using a control-flow keyword (break/continue/goto) at the end of a case. Using "continue" to fall through was rejected because it changes its meaning when there's a switch in a loop. You'd use goto <value> to jump to the particular (next) switch case. -- Best regards, Vladimir mailto:thecybershadow gmail.com
Oct 12 2009
On Mon, Oct 12, 2009 at 5:14 AM, Vladimir Panteleev <thecybershadow gmail.com> wrote:This was discussed before. IIRC, someone suggested to force using a control-flow keyword (break/continue/goto) at the end of a case. Using "continue" to fall through was rejected because it changes its meaning when there's a switch in a loop. You'd use goto <value> to jump to the particular (next) switch case."goto case;" already exists and jumps to the next case in the switch. So bam, you're already set ;)
Oct 12 2009
On Mon, Oct 12, 2009 at 04:03:13AM -0400, bearophile wrote:But the "-h" case misses a break.This has been discussed to death *multiple times*. Why bring it up again, especially with nothing really new to add to the argument? Here's what I suggest you do to get what you want: make a macro in your editor so whenever you type the word "case" it expands it to "break; case". And expand "default" to "break; default". Then, you'll get the implicit breaks you want without changing the language for the rest of us. -- Adam D. Ruppe http://arsdnet.net
Oct 12 2009
bearophile wrote:switch (arg) { case("-s") { try { next_arg = iargs.next(); size = toInt(args[idx++]); } catch (...) { throw new Exception("..."); } } case("-m") { printMessages = true; } case("-p") // just 1 istruction, no {} needed printResults = true; case("-h"); // semicolon isn't allowed here showUsage(); default { // default case may need some care throw new Exception("..."); } }You can do something like this: void main(string[] args) { auto t = ["-s"[]: { writefln("handle argument -s"); }, "-m": { writefln("handle argument -m"); }]; if (auto pcode = args[1] in t) { (*pcode)(); } else { //default case } } Even the ugly and unneeded case labels are gone! If you don't mind your ulta-modern switch-case to allocate memory when it's used. If you still don't like it, you can do some ugly mixin() and CTFE stuff. Nobody will mind because that's modern D style.
Oct 12 2009
grauzone wrote:bearophile wrote:import std.getopt; void main(string[] args) { getopt(args, "s", { writefln("handle argument -s"); }, "-m", { writefln("handle argument -m"); }); ... } Andreiswitch (arg) { case("-s") { try { next_arg = iargs.next(); size = toInt(args[idx++]); } catch (...) { throw new Exception("..."); } } case("-m") { printMessages = true; } case("-p") // just 1 istruction, no {} needed printResults = true; case("-h"); // semicolon isn't allowed here showUsage(); default { // default case may need some care throw new Exception("..."); } }You can do something like this: void main(string[] args) { auto t = ["-s"[]: { writefln("handle argument -s"); }, "-m": { writefln("handle argument -m"); }]; if (auto pcode = args[1] in t) { (*pcode)(); } else { //default case } } Even the ugly and unneeded case labels are gone! If you don't mind your ulta-modern switch-case to allocate memory when it's used. If you still don't like it, you can do some ugly mixin() and CTFE stuff. Nobody will mind because that's modern D style.
Oct 12 2009
Andrei Alexandrescu Wrote:grauzone wrote:What's even better, modern D style allows you to work around some misdesigned/legacy language features.If you still don't like it, you can do some ugly mixin() and CTFE stuff. Nobody will mind because that's modern D style.import std.getopt; void main(string[] args) { getopt(args, "s", { writefln("handle argument -s"); }, "-m", { writefln("handle argument -m"); }); ... }
Oct 13 2009