November 15, 2009
Don wrote:
> And looking at how rarely it's actually used by someone who thinks he uses it a lot, convinces me that intentional use of fall-through is much less common than bugs introduced by leaving out a break statement.

Except that I cannot recall ever having a bug from leaving out a break <g>.
November 15, 2009
Don:

> I consider that fallthrough requires a non-empty statement. IE,
> case A:
> case B:
> case C:
>       dosomething();
>       break;
> 
> is not a real fallthrough; those would always be allowed.

In D this is the right way to write that:

case A, B, C:
    dosomething();
    break;

Bye,
bearophile
November 15, 2009
Walter Bright:

> Except that I cannot recall ever having a bug from leaving out a break <g>.

Even if that's true, fall-through bugs are well know, documented even.

Bye,
bearophile
November 15, 2009
Walter Bright:

> I just use whitespace:
> 
>       switch (c) {
>           case 1:
>               blah();
>               break;
> 
>           case 2:
>               blah();
>           case 3:
>               blah();
>               break;
>       }
> 
> Works fine.

If that's a try at something humorous I don't get it.

Bye,
bearophile
November 15, 2009
Walter Bright wrote:
> Michel Fortin wrote:
>> Hum two suggestions. Sometime I want fall-through when I write a switch, but I always make it clear that it isn't a bug by writing the intent in a short comment:
>>
>>     switch (c) {
>>         case 1:
>>             blah();
>>             break;
>>         case 2:
>>             blah();
>>             // fallthrough
>>         case 3:
>>             blah();
>>             break;
>>     }
> 
> I just use whitespace:
> 
>      switch (c) {
>          case 1:
>              blah();
>              break;
> 
>          case 2:
>              blah();
>          case 3:
>              blah();
>              break;
>      }
> 
> Works fine.

No whitespace works fine, too. I strongly advise requiring control flow at the end of the break. Your style notwithstanding, fall through *is* rare. It is also more brittle than goto case xxx; because it is not invariant to manual code motion. It does make sense to write more to achieve the more dangerous and less used result, than the other way around.

Andrei
November 15, 2009
Don wrote:
> Andrei Alexandrescu wrote:
>> Chad J wrote:
>>> So, switch-case statements are a frequent source of nasty bugs.  Fixing
>>> them (well) requires breaking backwards compatibility.
>>>
>>> Any chance this will happen for D2?
>>>
>>> (This is intended as more of a reminder and simple curiosity than a
>>> discussion.)
>>
>> I wish very much that a transferring control flow statement (break, return, goto etc.) is required at the end of each case. Then, the rare case when you want to break through is easy to implement as goto case xxx; and all is good.
>>
>> Walter's answer to that has put me to silence for good. "But I use fall-through all the time!" I then knew the feature will never make it.
> 
> Walter definitely *thinks* he uses fall-through all of the time. BUT...
> Does he *really* use it all the time? It's not a matter of opinion; it's an objective question, answerable since so much of his code is now publically available. I got a bit interested in knowing how much he does use it.
> 
> I consider that fallthrough requires a non-empty statement. IE,
> case A:
> case B:
> case C:
>      dosomething();
>      break;
> 
> is not a real fallthrough; those would always be allowed.
> 
> I looked through a couple of DMD files: parse.c, (the parser), and cod3.c (the largest file in the back-end).
> In cod3, there are 381 case statements. There are 3 occasions where fallthrough is used. In two of those cases, they fallthrough to a label where other cases have 'goto' that label. In the remaining case, the code which was fallen through was an assert and a debug print statement.
> 
> parse.c has 541 case statements, I didn't find any fallthroughs in the first half of the code, but I didn't look as thoroughly as I did in cod3.
> 
> Based on this, it looks to me as though Walter uses fall-through very, very rarely. Less than 1% of all case statements.
> For comparison, those files contain 178 and 137 gotos, respectively <g>.
> Walter does use 'goto'. He doesn't use fallthrough in switch statements.
> 
> It's actually not something I care about at all. But I think Walter's wrong about his coding style. And looking at how rarely it's actually used by someone who thinks he uses it a lot, convinces me that intentional use of fall-through is much less common than bugs introduced by leaving out a break statement.
> 
> An interesting result.
> But I'd much rather change Walter's mind about opPow() or the meta.compiles(XXX) proposal.

Don       <----------        genius

I understand that you're more interested about the issues that preoccupy you (and incidentally me) the most, but "switch" is a day-to-day programming (and programmer's) workhorse, so a change there might have a wider (and hopefully more positive) impact.


Andrei
November 15, 2009
Walter Bright wrote:
> Don wrote:
>> And looking at how rarely it's actually used by someone who thinks he uses it a lot, convinces me that intentional use of fall-through is much less common than bugs introduced by leaving out a break statement.
> 
> Except that I cannot recall ever having a bug from leaving out a break <g>.

I can. I'm not sure where that leaves us. Others - please add your experience.

Andrei
November 15, 2009
bearophile wrote:
> Walter Bright:
> 
>> Except that I cannot recall ever having a bug from leaving out a break <g>.
> 
> Even if that's true, fall-through bugs are well know, documented even.
> 
> Bye,
> bearophile

Link?

Andrei
November 15, 2009
Walter Bright wrote:
> Don wrote:
>> And looking at how rarely it's actually used by someone who thinks he uses it a lot, convinces me that intentional use of fall-through is much less common than bugs introduced by leaving out a break statement.
> 
> Except that I cannot recall ever having a bug from leaving out a break <g>.

That's because you're a cyborg.

Have some pity on us mere mortals ;)
November 15, 2009
On Sun, 15 Nov 2009 12:49:01 -0500, Chad J wrote:

> So, switch-case statements are a frequent source of nasty bugs.  Fixing them (well) requires breaking backwards compatibility.
> 
> Any chance this will happen for D2?

The phrase "snowball in hell" comes to mind.

> (This is intended as more of a reminder and simple curiosity than a
> discussion.)

And in spite of your good intentions (~ not a discussion ~) this will be
one ;-)

The Euphoria Programming language, which I'm helping to implement, has 'solved' this issue. This language is not a C-derived one so don't be alarmed at its apparent verbosity.

The default 'case' in a 'switch' is to not fall through; an implied 'break' is assumed at the end of each 'case' clause.

  switch Foo do
      case 1 then
         ... whatever for 1 ...
         ... does not fall through to the next case ...

      case 2, 3 then
         ... whatever for 2 and 3 ...
         ... does not fall through to the next case ...

      case 4 then
         ... whatever for 4 ...
         ... does not fall through to the next case ...

  end switch


However, the coder can change the default behaviour on a 'switch' statement by including the phrase 'with fallthru', thus changing the default behaviour such that each 'case' clause will fall through to the next case unless the coder uses an explicit 'break' statement. This, as you can see, is the DPL behaviour.

  switch Foo with fallthru do
      case 1 then
         ... whatever for 1 ...
         ... falls through to the next case ...

      case 2, 3 then
         ... whatever for 2 and 3 ...
         break   /* explicitly required to prevent falling through */

      case 4 then
         ... whatever for 4 ...
         ... falls through to the next case ...

  end switch


Further more, whatever the default behaviour for the 'switch', it can be adjusted on any of the 'case' clauses. This means that a by-default-break switch, can use the 'fallthru' statement to explicitly override the break default and fall through to the next case.

  switch Foo do /* by default, break */
      case 1 then
         ... whatever for 1 ...
         fallthru /* explicitly falls through */

      case 2, 3 then
         ... whatever for 2 and 3 ...
         ... implied break here ...

      case 4 then
         ... whatever for 4 ...
         ... implied break here ...

  end switch

In short, Euphoria allows for both ideologies to exist, and in fact to co-exist in peace. The standard default gives most protection from mistakes, but for those coders that like to keep on the edge, they can code with the level of risk that is acceptable to themselves.

I can see good reason for DPL to adopt a similar stance. I would suggest a new keyword to make things easier for coders (after all, that's why we have programming languages), but for those who see keywords as evil, I'm sure that someone can come up with another syntax that avoids a new keyword (at the expense of clarity) eg. "! break" or the old standby, "static" LOL.

-- 
Derek Parnell
Melbourne, Australia
skype: derek.j.parnell