November 15, 2009
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.)
November 15, 2009
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.


Andrei
November 15, 2009
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.)

The correct way to solve this is to create a new switch-case statement that doesn't suck. It would use a different syntax, and support spiffy stuff like pattern matching. If you wanted to use duff's device or need C compatibility, you still could use the old switch-case.
November 15, 2009
On 2009-11-15 12:54:02 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> said:

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

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

That way I can always tell when I read again the code wether this was intentional or not. It wouldn't hurt at all if that "fallthrough" comment became a keyword:

	switch (c) {
		case 1:
			blah();
			break;
		case 2:
			blah();
			fallthrough;
		case 3:
			blah();
			break;
	}

Now the intent is clear even for the compiler.

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/

November 15, 2009
Andrei Alexandrescu wrote:
> 
> 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.
> 

T_T

There has to be a better way to do fall-through.

Maybe...

switch(foo)
{
    case 0;
    case 1; bar = baz; // Executed if foo == 0
    case 2:
        doSomething(bar); // Executed for foo ∈ {0,1,2}
        break; //required for compile success.
}
November 15, 2009
Chad J wrote:
> 
> There has to be a better way to do fall-through.
> 
> Maybe...
> 
> switch(foo)
> {
>     case 0;
>     case 1; bar = baz; // Executed if foo == 0
>     case 2:
>         doSomething(bar); // Executed for foo ∈ {0,1,2}
>         break; //required for compile success.
> }

or if you want it to look nicer, maybe introduce an arrow token:

switch(foo)
{
    case 0 ->
    case 1 -> bar = baz; // Executed if foo == 0
    case 2:
        doSomething(bar); // Executed for foo ∈ {0,1,2}
        break; //required for compile success.
}

It has these advantages:
* Fall-through behavior is explicit.
* Fall-through notation requires no extra lines of source, and only a
couple extra columns.

Sigh, I didn't want to discuss syntax, but that response... it makes me want to solve problems, to say the least.
November 15, 2009
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.
> 
> 
> Andrei

For what its worth, in a (very domain specific) scripting language I've been working on, I used 'continue' to implement fall-through, and haven't felt too bad about it.  That and being able to do (case A, B, C:) helps for the most common (IME) sort of use.

//////////////////////////////////////////////////
.__receive system ( cmd: STR, @params )
    switch ( cmd .lowercase .tosym )
        case 'lo', 'login':
            user.tell( "(LOgin has been deprecated; please start using COnnect instead.)")
            continue;

        case 'co', 'connect':
            uname, pwd <- params;
            who = #Database::User.lookup( uname )
            if ( who.valid && who.accept_password( pwd ) )
		return .accept( user, who );
            end

        // ... and so on ...
    end
end
//////////////////////////////////////////////////

-- Chris Nicholson-Sauls
November 15, 2009
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.
November 15, 2009
Chris Nicholson-Sauls wrote:
> For what its worth, in a (very domain specific) scripting language I've been working on, I used 'continue' to implement fall-through, and haven't felt too bad about it.

Using "continue" for that purpose would silently break a lot of existing code.
November 15, 2009
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.
« First   ‹ Prev
1 2 3 4 5 6 7 8
Top | Discussion index | About this forum | D home