switch()

Manu turkeyman at gmail.com
Sun Feb 16 08:08:51 PST 2014


Another thing that I often do is switch on an expression, but I often have
a problem where, within the scope, I have no way to refer to the result
value.
This is particularly important when range cases appear.

switch(x+10)
{
  case 10: .. case 20:
    // what is the value?
}

Obviously then I need to do this:

auto y = x+10;
switch(y)
{
  case 10: .. case 20:
    // I know y...
}

But this is a bit lame. I'm polluting the outer namespace, and wasting a
line.

I wonder if a variable declaration could be made possible in the switch:

switch(y = x+10) // obviously implicitly auto, like in foreach
{
  case 10: .. case 20:
    // I have y, no pollution of the outer scope, no wasted line. yay!
}

for and foreach can both declare variables this way... does it make sense
here? Useful?



On 17 February 2014 01:42, Manu <turkeyman at gmail.com> 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".
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20140217/500bc8dc/attachment-0001.html>


More information about the Digitalmars-d mailing list