switch()

Damian Day damianroyday at gmail.com
Mon Feb 17 02:19:44 PST 2014


On Sunday, 16 February 2014 at 15:43:31 UTC, Manu wrote:
> So D offers great improvements to switch(), but there are a few 
> small
> things I wonder about.
>
> 1.
> case fall-through is not supported; explicit 'goto case n;' is 
> required.
> With this in mind, 'break' is unnecessary. Why is it required? 
> It could be
> implicit upon reaching the next case label, or a scope could be 
> used (with
> support for omitting the scope for single statements as with 
> if).
> It's really noisy, and annoying to write everywhere.
>
> 2.
> 'case 1, 3, 7, 8:' is awesome! ...but ranged cases have a 
> totally different
> syntax: 'case 1: .. case 3:'
>
> Why settle on that syntax? The inconsistency looks kinda silly 
> when they
> appear together in code.
> Surely it's possible to find a syntax that works without 
> repeating case and
> ':'?
>
> It's also weird, because it seems that 'case n: .. case m:' is 
> inclusive of
> m. This may be unexpected.
> I'm not sure it's reasonable to use the '..' syntax in this 
> case for that
> reason. '..' is an [) range, case ranges must be [] so that it 
> makes sense
> when dealing with enum key ranges.
>
> 3.
> Why is 'default' necessary? If I'm not switching on an 
> enumerated type,
> then many values are meaningless. requiring an empty 'default: 
> break;' line
> at the end is annoying and noisy.
>
> I often find myself tempted to rewrite blocks of successive 
> if() logic
> comparing integers against values/ranges, but it looks silly 
> since the
> scope rules are not explicit, and 'default: break;' always 
> wastes an extra
> line.
> I like to reduce noise in my code, and these switch semantics 
> threaten to
> simplify a lot of code, if not for these strange decisions 
> (purely for
> legacy compliance?).
>
>
> Let's consider an example:
>
> Code like this:
>
> int difficulty = -1;
> if(e.note.note >= 60 && e.note.note < 72)
> difficulty = 0;
> else if(e.note.note >= 72 && e.note.note < 84)
> difficulty = 1;
> else if(e.note.note >= 84 && e.note.note < 96)
> difficulty = 2;
> else if(e.note.note >= 96 && e.note.note < 108)
> difficulty = 3;
>
> The repetition of e.note.note is annoying, and particular 
> choice of
> comparisons are liable to result in out-by-ones. It's not nice 
> code to read.
>
>
> Rewrites like this:
>
> int difficulty;
> switch(e.note.note)
> {
> case 60: .. case 71:
> difficulty = 0;
> break;
> case 72: .. case 83:
> difficulty = 1;
> break;
> case 84: .. case 95:
> difficulty = 2;
> break;
> case 96: .. case 107:
> difficulty = 3;
> break;
> default:
> difficulty = -1;
> break;
> }
>
> That's horrid, it's much longer! And there are pointless wasted 
> lines
> everywhere.
> The default case is a total waste, since -1 should just be 
> assigned when
> initialising the variable above.
>
>
> We can compact it a bit like this:
>
> int difficulty;
> switch(e.note.note)
> {
> case 60: .. case 71:
> difficulty = 0; break;
> case 72: .. case 83:
> difficulty = 1; break;
> case 84: .. case 95:
> difficulty = 2; break;
> case 96: .. case 107:
> difficulty = 3; break;
> default:
> difficulty = -1; break;
> }
>
> But that's horrible too. It's not clear what vertical offset 
> the 'break'
> statements shoudl appear at (I hate stacking up multiple 
> statements across
> the same line!).
> The the default case is still a waste.
>
>
> Ideally:
>
> int difficulty = -1;
> switch(e.note.note)
> {
> case 60 .. 72:
> difficulty = 0;
> case 72 .. 84:
> difficulty = 1;
> case 84 .. 96:
> difficulty = 2;
> case 96 .. 108:
> difficulty = 3;
> }
>
> 'break's are unnecessary since fallthrough isn't allowed.
> Proper numeric range could be supported (assuming [) intervals).
> 'default' case is unnecessary, and removed.
>
> The switch and braces results in 3 extra lines, but I still 
> feel this level
> of simplification results in code that is MUCH more readable 
> than the
> sequence of if's I started with. It's super obvious what's 
> going on.
>
> I have quite many blocks like this.
>
> A great man once (actually, frequently) said "If it doesn't 
> look right, it
> probably isn't".


Having also wrote a lot of switch statements in D I do mostly
agree on these points. I think this example 'case 1: .. case 3:'
is obvious. but I like 'case 1..3, 5, 6, 8, 9..10:' syntax better
(Pascal) see how much typing I save.

Break inside a switch should be rid of (Again Pascal) it's bloat.

Having a default does get a bit annoying I see a lot of these..
That being said it's nice having that extra safety.


More information about the Digitalmars-d mailing list