switch()

Timon Gehr timon.gehr at gmx.ch
Sun Feb 16 09:14:48 PST 2014


On 02/16/2014 04:42 PM, 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.

Yes it is supported. Use 'goto case;'.

> With this in mind, 'break' is unnecessary.

Sure.

> Why is it required?

Backwards compatibility.

> 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.
> ...

Like this: 
http://ceylon-lang.org/documentation/reference/statement/switch/ ?


> 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 ':'?
> ...

AFAIK it is to emphasize that the range is inclusive, as opposed to:

case 1..3:

IIRC Walter's intention was to format it as follows:

switch(x){
     case 1:
     ..
     case 3:
}


> 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.
> ...

Sure, mixing case lists and ranges in a single statement would be neat, 
but what would be your preferred syntax?

> 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.
> ...

There is more than one sensible default, so being explicit about the 
default makes sense.


> 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 wasted lines are due to your formatting.

int difficulty=-1;
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: break;
}

Of course, I'd just write the above as:

int difficulty = e.note.note.between(60,108) ? (e.note.note-60)/12 : -1;

> The default case is a total waste, since -1 should just be assigned when
> initialising the variable above.
> ...

How is the compiler supposed to know? It might be a logic error for 
e.note.note to be out of range.

>...
>
> 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;
> }
> ...

Ideally closer to:

int difficulty =
   switch(e.note.note){
       60 .. 72  =>  0;
       73 .. 84  =>  1;
       84 .. 96  =>  2;
       96 .. 108 =>  3;
       _         => -1;
   };





More information about the Digitalmars-d mailing list