Re: final switch and straight integers
On Thursday, 21 April 2016 at 12:45:34 UTC, Steven Schveighoffer wrote: On 4/19/16 6:04 PM, Stefan Koch wrote: On Tuesday, 19 April 2016 at 14:53:18 UTC, Steven Schveighoffer wrote: or we should do away with requiring handling all enum cases. Are you suggesting getting rid of final switch ? No, what I'm suggesting is that final switch behave consistently. For integers, final switch doesn't require all possible values be handled, but for enums it does. One way to make this consistent is to not require all enums be handled. I'm not suggesting that this is the best answer, just that it is a possible way to square the inconsistency. Note that even with final switch on an enum, you have issues, especially if the enum is considered to be a bitfield: enum bitfield { flag1 = 1 << 0, flag2 = 1 << 1 } `final enum` was suggested for strict enums that can't be used as flags. If we had that, we could phase out `final switch` on non-strict enums.
Re: final switch and straight integers
On 4/20/16 4:23 AM, Johan Engelen wrote: On Wednesday, 20 April 2016 at 06:36:01 UTC, bearophile wrote: It's easy to cover all the values in a switch, using ranges. Not as easy as you would think: int i; switch(i) { case 0: .. case 9: break; case 10: ..case 1000: break; default: break; } --> Error: had 990 cases which is more than 256 cases in case range The FE always lowers CaseRangeStatements into a list of CaseStatements, so LDC currently has the same limitation. Um... this seems a horrid limitation. -Steve
Re: final switch and straight integers
On 4/19/16 6:04 PM, Stefan Koch wrote: On Tuesday, 19 April 2016 at 14:53:18 UTC, Steven Schveighoffer wrote: or we should do away with requiring handling all enum cases. Are you suggesting getting rid of final switch ? No, what I'm suggesting is that final switch behave consistently. For integers, final switch doesn't require all possible values be handled, but for enums it does. One way to make this consistent is to not require all enums be handled. I'm not suggesting that this is the best answer, just that it is a possible way to square the inconsistency. Note that even with final switch on an enum, you have issues, especially if the enum is considered to be a bitfield: enum bitfield { flag1 = 1 << 0, flag2 = 1 << 1 } ... void foo(bitfield x) final switch(x) { case flag1: writeln("flag1"); break; case flag2: writeln("flag2"); break; } This compiles, but doesn't handle flag1 | flag2. So final switch isn't helping to cover all cases. In other cases, you may have a member of an enum that isn't ever used as a value, but you have to cover it: enum message { foo, bar, mask = foo | bar } final switch is nice when you fit into the use case. When not, you have to fall back to normal switch. I find many times wanting to use final switch but having to follow the rules would make it look silly. -Steve
Re: final switch and straight integers
On Wednesday, 20 April 2016 at 17:42:03 UTC, Basile Burg wrote: On Wednesday, 20 April 2016 at 10:19:17 UTC, Dominikus Dittes Scherkl wrote: Anyway, something need to be changed. a) allow Range Cases (nice for ints but bad idea for enums) b) require also non-enum types to explicitly state all cases (bad idea for any multi-byte type, even near useless for single bytes) c) forbid other types than enum in final switch I strongly vote for (c). A good `int` value for a variable `int x` can be enforced (min(), max(), clamping, warping, etc) **before** a final switch(x). No, because final switch requires you to enumerate all possible cases. If c) is done then the compiler in this cas would disallow something that's completly safe (generally speaking I mean, here safe == no SwitchException possible). Why would you ever want to use final switch on int? Why not simply use the normal switch? Especially if you enforced a useful range with min(), max(), etc. would it not be better to do the remaining cases manually? (or even do the range check in the default case?)
Re: final switch and straight integers
On Wednesday, 20 April 2016 at 10:19:17 UTC, Dominikus Dittes Scherkl wrote: Anyway, something need to be changed. a) allow Range Cases (nice for ints but bad idea for enums) b) require also non-enum types to explicitly state all cases (bad idea for any multi-byte type, even near useless for single bytes) c) forbid other types than enum in final switch I strongly vote for (c). A good `int` value for a variable `int x` can be enforced (min(), max(), clamping, warping, etc) **before** a final switch(x). If c) is done then the compiler in this cas would disallow something that's completly safe (generally speaking I mean, here safe == no SwitchException possible).
Re: final switch and straight integers
On Wednesday, 20 April 2016 at 07:23:09 UTC, Bastiaan Veelo wrote: On Wednesday, 20 April 2016 at 07:18:55 UTC, Bastiaan Veelo wrote: On Wednesday, 20 April 2016 at 06:36:01 UTC, bearophile wrote: Dominikus Dittes Scherkl: final switch makes no sense on things that are not enumerated. Even on ubyte almost nobody will ever list all 256 cases, not to mention larger types. It's easy to cover all the values in a switch, using ranges. 2. No CaseRangeStatements are allowed. Sorry, pressed Send too early. You mean implement to remove the above limitation? Anyway, something need to be changed. a) allow Range Cases (nice for ints but bad idea for enums) b) require also non-enum types to explicitly state all cases (bad idea for any multi-byte type, even near useless for single bytes) c) forbid other types than enum in final switch I strongly vote for (c).
Re: final switch and straight integers
On Wednesday, 20 April 2016 at 06:36:01 UTC, bearophile wrote: It's easy to cover all the values in a switch, using ranges. Not as easy as you would think: int i; switch(i) { case 0: .. case 9: break; case 10: ..case 1000: break; default: break; } --> Error: had 990 cases which is more than 256 cases in case range The FE always lowers CaseRangeStatements into a list of CaseStatements, so LDC currently has the same limitation.
Re: final switch and straight integers
On Wednesday, 20 April 2016 at 07:18:55 UTC, Bastiaan Veelo wrote: On Wednesday, 20 April 2016 at 06:36:01 UTC, bearophile wrote: Dominikus Dittes Scherkl: final switch makes no sense on things that are not enumerated. Even on ubyte almost nobody will ever list all 256 cases, not to mention larger types. It's easy to cover all the values in a switch, using ranges. 2. No CaseRangeStatements are allowed. Sorry, pressed Send too early. You mean implement to remove the above limitation?
Re: final switch and straight integers
On Wednesday, 20 April 2016 at 06:36:01 UTC, bearophile wrote: Dominikus Dittes Scherkl: final switch makes no sense on things that are not enumerated. Even on ubyte almost nobody will ever list all 256 cases, not to mention larger types. It's easy to cover all the values in a switch, using ranges. 2. No CaseRangeStatements are allowed.
Re: final switch and straight integers
Dominikus Dittes Scherkl: final switch makes no sense on things that are not enumerated. Even on ubyte almost nobody will ever list all 256 cases, not to mention larger types. It's easy to cover all the values in a switch, using ranges. No need to forbid final switch for integral values. It just needs to be implemented correctly. Bye, bearophile
Re: final switch and straight integers
On Tuesday, 19 April 2016 at 22:04:21 UTC, Stefan Koch wrote: On Tuesday, 19 April 2016 at 14:53:18 UTC, Steven Schveighoffer wrote: or we should do away with requiring handling all enum cases. Are you suggesting getting rid of final switch ? No - I think he suggests to error out if final switch is used on something other than enums. I support this suggestion, final switch makes no sense on things that are not enumerated. Even on ubyte almost nobody will ever list all 256 cases, not to mention larger types.
Re: final switch and straight integers
On Tuesday, 19 April 2016 at 14:53:18 UTC, Steven Schveighoffer wrote: or we should do away with requiring handling all enum cases. Are you suggesting getting rid of final switch ?
final switch and straight integers
I was surprised that in my code, I had a final switch on an integer, and compiler never complained. I looked at the rules here: http://dlang.org/spec/statement.html#final-switch-statement Rules are: 1. No DefaultStatement is allowed. 2. No CaseRangeStatements are allowed. 3. If the switch Expression is of enum type, all the enum members must appear in the CaseStatements. 4. The case expressions cannot evaluate to a run time initialized value. What if expression is not of enum type? Apparently that just means no default statement is required. In other words: void foo(int x) { final switch(x) { case 0: break; } } compiles. I was surprised about this, apparently it just means throw an error if no case is matched. I don't see a lot of value in this over a straight switch statement. Is there something I'm missing? I find this inconsistent with the enum version -- shouldn't I have to handle all possible values? I think either rule 3 should remove the qualifier "If the expression is of enum type" and qualify rule 2 which only would make sense for enums, or we should do away with requiring handling all enum cases. -Steve