February 19, 2014
"Steven Schveighoffer"  wrote in message news:op.xbhnw5rbeav7ka@stevens-macbook-pro.local...

> It may not be mindless. Most people who want to handle the default case do it. It's usually not so much "I didn't think of handling other values," it's more "I never expect other values to come in, go away annoying compiler error."

So why not put an assert(0) in instead of a break?  Tell the compiler that you're assuming there are no other possible values.  This is obviously the right thing to do here, and even if you ignore it the compiler _is_ trying to help you.

> I think it's the same as saying you have to always have an else clause after an if statement, even if it's "else {}"

If 'if' was primarily used for the same thing that switch is, this would be perfectly reasonable. 

February 19, 2014
On Tuesday, 18 February 2014 at 15:45:31 UTC, Ary Borenszweig wrote:
> Exactly. Programmers will just put "default: break" because of this annoyance without thinking too much if it should be this or assert(0).
>
> I think that "final switch" should have the function of checking that you covered all cases, be it with a default case or not.

A better warning/error message may help here. Please have a look at this PR:

https://github.com/D-Programming-Language/dmd/pull/3287
February 19, 2014
On Tuesday, 18 February 2014 at 02:55:10 UTC, Manu wrote:
> Me too, but you don't feel this is basically a hack?
> About half of that text is repeated cruft, and there's no precedent for
> formatting well-structured code like that anywhere else in the language.

There are other ways in D to deal with repetition. For people coming from C/C++ some of these tricks are unnatural because programmers writing in those prefer to just write everything "inline" for performance reasons.

So, possible sollutions:

- go make a function:

getDifficulty(int note) {
switch(note)
{
case 60: .. case 71:  return 0;
case 72: .. case 83:  return 1;
case 84: .. case 95:  return 2;
case 96: .. case 107: return 3;
default: return -1;
}
}

and then
difficulty = getDifficulty(e.note.note);

- you can make this function local if it's not needed anywhere, local functions are awesome - they reduce a lot of code duplication. Any code that repeats inside a local scope can be put inside a local function

- you can also make e.note a real type with a method instead of inlining the logic in place and call e.note.getDifficulty or whatever

If your code is full of switch-cases you should probably use polymorphism instead (virtual dispatch, omg).

February 19, 2014
On 2/19/14, 6:42 AM, Daniel Murphy wrote:
>
> "Steven Schveighoffer"  wrote in message
> news:op.xbhnw5rbeav7ka@stevens-macbook-pro.local...
>
>> It may not be mindless. Most people who want to handle the default
>> case do it. It's usually not so much "I didn't think of handling other
>> values," it's more "I never expect other values to come in, go away
>> annoying compiler error."
>
> So why not put an assert(0) in instead of a break?  Tell the compiler
> that you're assuming there are no other possible values.  This is
> obviously the right thing to do here, and even if you ignore it the
> compiler _is_ trying to help you.

Sometimes you don't care about other values, which is different than not expecting other values. For example:

auto a = ...;
switch(a) {
  case 1: a += 1;
  case 2: a += 2;
  // In other cases, leave "a" as is
}


February 19, 2014
On Wednesday, 19 February 2014 at 14:14:01 UTC, Ary Borenszweig wrote:
> On 2/19/14, 6:42 AM, Daniel Murphy wrote:
>>
>> "Steven Schveighoffer"  wrote in message
>> news:op.xbhnw5rbeav7ka@stevens-macbook-pro.local...
>>
>>> It may not be mindless. Most people who want to handle the default
>>> case do it. It's usually not so much "I didn't think of handling other
>>> values," it's more "I never expect other values to come in, go away
>>> annoying compiler error."
>>
>> So why not put an assert(0) in instead of a break?  Tell the compiler
>> that you're assuming there are no other possible values.  This is
>> obviously the right thing to do here, and even if you ignore it the
>> compiler _is_ trying to help you.
>
> Sometimes you don't care about other values, which is different than not expecting other values. For example:
>
> auto a = ...;
> switch(a) {
>   case 1: a += 1;
>   case 2: a += 2;
>   // In other cases, leave "a" as is
> }

Just put default: break instead of that comment, it's shorter that way:P
February 20, 2014
On Wed, 19 Feb 2014 09:17:58 -0500, QAston <qaston@gmail.com> wrote:

> On Wednesday, 19 February 2014 at 14:14:01 UTC, Ary Borenszweig wrote:
>> auto a = ...;
>> switch(a) {
>>   case 1: a += 1;
>>   case 2: a += 2;
>>   // In other cases, leave "a" as is
>> }
>
> Just put default: break instead of that comment, it's shorter that way:P

I think the comment was meant as an explanation to you, not something that would actually be in the code :)

-Steve
February 20, 2014
On Tue, 18 Feb 2014 17:37:43 -0500, Walter Bright <newshound2@digitalmars.com> wrote:

> On 2/18/2014 8:38 AM, Steven Schveighoffer wrote:
>> My point though, is that the change to require default gains you nothing except
>> annoyed programmers. Why put it in?
>
> This was fiercely debated at length and settled here years ago. It isn't going to change.

I thought it was a more recent change than years ago. When was the change made? Looking it up, looks like 2011. That was a long time ago, longer than I thought.

>> The comparison I AM making is that we are implementation a requirement that will
>> not achieve the behavior goal it sets out to achieve.
>
> It's been this way for years now, if there was emergent bad behavior, it would be obvious by now. But I haven't heard any reports of such.

Emergent bad behavior is not the result I would expect. Most likely, leaving out the default case was not an error. If this fixed a "bug" that didn't exist, the fact that bad behavior didn't result isn't really informative.

What I really would be curious about is if in most D code, you see a lot more default: break; than default: assert(0);

In any case, I am not vehemently against requiring a default case, it's not terrible to put in default: break; I just find it somewhat puzzling that it's required.

-Steve
February 20, 2014
On Wed, 19 Feb 2014 04:42:19 -0500, Daniel Murphy <yebbliesnospam@gmail.com> wrote:

>
> "Steven Schveighoffer"  wrote in message news:op.xbhnw5rbeav7ka@stevens-macbook-pro.local...
>
>> It may not be mindless. Most people who want to handle the default case do it. It's usually not so much "I didn't think of handling other values," it's more "I never expect other values to come in, go away annoying compiler error."
>
> So why not put an assert(0) in instead of a break?  Tell the compiler that you're assuming there are no other possible values.  This is obviously the right thing to do here, and even if you ignore it the compiler _is_ trying to help you.

Putting default: assert(0); changes the meaning of the code. In other words:

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

is the same as:

switch(x)
{
   case 1: ...
   default: break;
}

You are keeping the code the same. I don't think people would think of adding the assert(0), I wouldn't.

And as Ary pointed out, it may be that you expect the default to occur, but don't want to do anything.

>> I think it's the same as saying you have to always have an else clause after an if statement, even if it's "else {}"
>
> If 'if' was primarily used for the same thing that switch is, this would be perfectly reasonable.

'if' and 'switch' are commonly used interchangeably. Frequently one uses 'switch' where they would normally use 'if' to avoid evaluating something multiple times.

-Steve
February 20, 2014
Steven Schveighoffer:

> What I really would be curious about is if in most D code, you see a lot more default: break; than default: assert(0);

I have written tons of D2 code in the last years, and such "default: assert(0);" is quite uncommon in my code. Probably less than 8-10 usages in the whole code base.

Bye,
bearophile
February 20, 2014
"Steven Schveighoffer"  wrote in message news:op.xbk44onleav7ka@stevens-macbook-pro.local...

> What I really would be curious about is if in most D code, you see a lot more default: break; than default: assert(0);

I just did a quick git-grep on the compiler source (not D, but all switches do have a default thanks to the d port)

With 707 "default:"s 68 had a break on either the same or next line, and 249 had an assert(0).

On phobos I get 22 assert(0)s vs 10 breaks with 147 defaults

With druntime i get 24 assert(0)s + 5 error();s vs 11 breaks with 64 defaults.