View mode: basic / threaded / horizontal-split · Log in · Help
January 03, 2008
Re: No more fall through in case statement?
Bill Baxter:
> I'm no C# guy but that looks like a nice way to fix C's switch.

I think the C switch is broken in 2 or more ways, so I'd like to see D improve it. This is some code I have shown time ago:

import std.stdio: writefln;
void main(string[] args) {
 switch (args[1]) {
   int x = 1; // NOT initialized?
   case "1": writefln("1! x=", x); break;
   case "2": writefln("2! x=", x); break;
 }
}

More on switch-induced bugs:
http://www.soft.com/AppNotes/attcrash.html


>"goto case 5" looks like something straight out of Walter's playbook, too.<

I don't like that goto too much... You usually just want do go down (and by default you want to go to the end of the switch).


> But it's been discussed many times now and it doesn't seem likely Walter's going to change it in D.<

I agree with Walter when he says it's better that if a syntax that looks like C works like C (D goes against this rule few times). So we need a syntax that looks different. Instead of switch{} it may be used caseof{}, plus the "default" statement, plus a new statement like "fall" (or something similar) that tells the compiler just to not break, so it's just the opposite of C :-)

As example, this is a part of the std.string.capwords function:

switch (s[i]) {
   case ' ':
   case '\t':
   case '\f':
   case '\r':
   case '\n':
   case '\v':
       if (inword) {
           r ~= capitalize(s[istart .. i]);
           inword = false;
       }
       break;

   default:
       if (!inword) {
           if (r.length)
           r ~= ' ';
           istart = i;
           inword = true;
       }
       break;
}


With that syntax it becomes:

caseof (s[i]) {
   case ' ':  fall;
   case '\t': fall;
   case '\f': fall;
   case '\r': fall;
   case '\n': fall;
   case '\v':
       if (inword) {
           r ~= capitalize(s[istart .. i]);
           inword = false;
       }

   default:
       if (!inword) {
           if (r.length)
           r ~= ' ';
           istart = i;
           inword = true;
       }
}


D already follows such "inversion rule" regerding C in some cases, like here:

int a = void;

In a safe(r) language the default syntax/behavior *must* be the safer one, expecially when this has no/little costs in terms of speed/memory.

Bye,
bearophile
January 03, 2008
Re: No more fall through in case statement?
bearophile:

> caseof (s[i]) {
>     case ' ':  fall;
>     case '\t': fall;
>     case '\f': fall;
>     case '\r': fall;
>     case '\n': fall;
>     case '\v':
>         if (inword) {
>             r ~= capitalize(s[istart .. i]);
>             inword = false;
>         }
> 
>     default:
>         if (!inword) {
>             if (r.length)
>             r ~= ' ';
>             istart = i;
>             inword = true;
>         }
> }

Let's try again, 2 keywords less:

caseof (s[i]) {
   case ' ':  continue;
   case '\t': continue;
   case '\f': continue;
   case '\r': continue;
   case '\n': continue;
   case '\v':
       if (inword) {
           r ~= capitalize(s[istart .. i]);
           inword = false;
       }

   else:
       if (!inword) {
           if (r.length)
           r ~= ' ';
           istart = i;
           inword = true;
       }
}

:-)

Bye,
bearophile
January 03, 2008
Re: No more fall through in case statement?
bearophile Wrote:

> bearophile:
> 
> > caseof (s[i]) {
> >     case ' ':  fall;
> >     case '\t': fall;
> >     case '\f': fall;
> >     case '\r': fall;
> >     case '\n': fall;
> >     case '\v':
> >         if (inword) {
> >             r ~= capitalize(s[istart .. i]);
> >             inword = false;
> >         }
> > 
> >     default:
> >         if (!inword) {
> >             if (r.length)
> >             r ~= ' ';
> >             istart = i;
> >             inword = true;
> >         }
> > }
> 
> Let's try again, 2 keywords less:
> 
> caseof (s[i]) {
>     case ' ':  continue;
>     case '\t': continue;
>     case '\f': continue;
>     case '\r': continue;
>     case '\n': continue;
>     case '\v':
>         if (inword) {
>             r ~= capitalize(s[istart .. i]);
>             inword = false;
>         }
> 
>     else:
>         if (!inword) {
>             if (r.length)
>             r ~= ' ';
>             istart = i;
>             inword = true;
>         }
> }
> 
> :-)
> 
> Bye,
> bearophile

I doubt that 'continue' can be used there - what if we have a caseof in a loop?

foreach(x; y)
{
   caseof(s[i])
   {
        case '': continue; // fallthrough or continue the loop?
   }
}

One could workaround this by giving the loop a label and using it
with 'continue', but still, this might be confusing for beginners.
January 03, 2008
Re: No more fall through in case statement?
Leonard Dahlmann wrote:
> I doubt that 'continue' can be used there - what if we have a caseof in a loop?

Same with 'break' - what if we have a switch in a loop? =)

regards, frank
January 03, 2008
Re: No more fall through in case statement?
bearophile escribió:
> Bill Baxter:
>> I'm no C# guy but that looks like a nice way to fix C's switch.
>
> I think the C switch is broken in 2 or more ways, so I'd like to see D 
improve it. This is some code I have shown time ago:
>
> import std.stdio: writefln;
> void main(string[] args) {
>   switch (args[1]) {
>     int x = 1; // NOT initialized?
>     case "1": writefln("1! x=", x); break;
>     case "2": writefln("2! x=", x); break;
>   }
> }
>
> More on switch-induced bugs:
> http://www.soft.com/AppNotes/attcrash.html
>
>
>> "goto case 5" looks like something straight out of Walter's playbook, too.<
>
> I don't like that goto too much... You usually just want do go down (and by 
default you want to go to the end of the switch).
>
>
>> But it's been discussed many times now and it doesn't seem likely Walter's 
going to change it in D.<
>
> I agree with Walter when he says it's better that if a syntax that looks like 
C works like C (D goes against this rule few times). So we need a syntax that 
looks different. Instead of switch{} it may be used caseof{}, plus the "default" 
statement, plus a new statement like "fall" (or something similar) that tells 
the compiler just to not break, so it's just the opposite of C :-)
>
> As example, this is a part of the std.string.capwords function:
>
> switch (s[i]) {
>     case ' ':
>     case '\t':
>     case '\f':
>     case '\r':
>     case '\n':
>     case '\v':
>         if (inword) {
>             r ~= capitalize(s[istart .. i]);
>             inword = false;
>         }
>         break;
>
>     default:
>         if (!inword) {
>             if (r.length)
>             r ~= ' ';
>             istart = i;
>             inword = true;
>         }
>         break;
> }
>
>
> With that syntax it becomes:
>
> caseof (s[i]) {
>     case ' ':  fall;
>     case '\t': fall;
>     case '\f': fall;
>     case '\r': fall;
>     case '\n': fall;
>     case '\v':
>         if (inword) {
>             r ~= capitalize(s[istart .. i]);
>             inword = false;
>         }
>
>     default:
>         if (!inword) {
>             if (r.length)
>             r ~= ' ';
>             istart = i;
>             inword = true;
>         }
> }
>

How about using existing D syntax?

switch (s[i]) {
     case ' ', '\t', '\f', '\r', '\n', '\v':
         if (inword) {
             r ~= capitalize(s[istart .. i]);
             inword = false;
         }
         break;

     default:
         if (!inword) {
             if (r.length)
             r ~= ' ';
             istart = i;
             inword = true;
         }
         break;
}

>
> D already follows such "inversion rule" regerding C in some cases, like here:
>
> int a = void;
>
> In a safe(r) language the default syntax/behavior *must* be the safer one, 
expecially when this has no/little costs in terms of speed/memory.
>
> Bye,
> bearophile



-- 
Carlos Santander Bernal
January 04, 2008
Re: No more fall through in case statement?
Carlos Santander Wrote:
> 
> How about using existing D syntax?
> 
> switch (s[i]) {
>       case ' ', '\t', '\f', '\r', '\n', '\v':
>           if (inword) {
>               r ~= capitalize(s[istart .. i]);
>               inword = false;
>           }
>           break;
> 
>       default:
>           if (!inword) {
>               if (r.length)
>               r ~= ' ';
>               istart = i;
>               inword = true;
>           }
>           break;
> }

This whole conversation about switch was kind of lost on me, but I have to contribute this.

I, at various times, have written code that depends on case statements falling through, while not being identical!

For example:

switch(foo)
{
case 'bob':
   //Do bob stuff
   //Fall through and doo bar stuff too.
case 'bar':
   //Do bar stuff and exit   
   break;

case 'baz':
  //Do some baz stuff
  break;
}

Whatever is changed shouldn't break this.
January 04, 2008
Re: No more fall through in case statement?
S. wrote:

> This whole conversation about switch was kind of lost on me, 

Don't worry, none of it will ever happen in D, anyway.

> but I have to contribute this.
> I, at various times, have written code that depends on case statements falling through, while not being identical!
> 
> For example:
> 
> switch(foo)
> {
> case 'bob':
>     //Do bob stuff
>     //Fall through and doo bar stuff too.
> case 'bar':
>     //Do bar stuff and exit   
>     break;
> 
> case 'baz':
>    //Do some baz stuff
>    break;
> }
> 
> Whatever is changed shouldn't break this.

Good news for you, then.  Nothing's going to change!

But man I wish it would, for 2.0 that is.  I've been hit at least 
half-a-dozen times in the past year by missing break statements in my D 
code.  And I have a C++ background!  So it's not about familiarity.  It 
bites me when I'm coding C++ just as frequently.  It's simply a C/C++ 
mis-feature that D failed to correct.

--bb
January 04, 2008
Re: No more fall through in case statement?
S. Wrote:
> I, at various times, have written code that depends on case statements falling through, while not being identical!

If you take a look at my original post, I have suggested to use a "fall" or "continue" statement when you want to go down, and nothing if you want the default of going at the end of the switch...

Bye,
bearophile
January 04, 2008
Re: No more fall through in case statement?
On Fri, 04 Jan 2008 00:15:25 -0000, S. <S@s.com> wrote:

> Carlos Santander Wrote:
>>
>> How about using existing D syntax?
>>
>> switch (s[i]) {
>>       case ' ', '\t', '\f', '\r', '\n', '\v':
>>           if (inword) {
>>               r ~= capitalize(s[istart .. i]);
>>               inword = false;
>>           }
>>           break;
>>
>>       default:
>>           if (!inword) {
>>               if (r.length)
>>               r ~= ' ';
>>               istart = i;
>>               inword = true;
>>           }
>>           break;
>> }
>
> This whole conversation about switch was kind of lost on me, but I have  
> to contribute this.
>
> I, at various times, have written code that depends on case statements  
> falling through, while not being identical!
>
> For example:
>
> switch(foo)
> {
> case 'bob':
>     //Do bob stuff
>     //Fall through and doo bar stuff too.
> case 'bar':
>     //Do bar stuff and exit
>     break;
>
> case 'baz':
>    //Do some baz stuff
>    break;
> }
>
> Whatever is changed shouldn't break this.

This whole conversation boggles me. cases should *never* fall through its  
dangerous.
Assuming polymorphism isn't the answer, which can often eliminate the  
switch altogether
its much cleaner, safer and better encapsulated in general to use a  
function call
to replace fall through. E.g. :

handleBar()
{
  //Do bar stuff
}

switch(foo)
{
case 'bob':
    // do bob stuff
    handleBar();
case 'bar':
    handleBar();
case 'baz':
    // do baz stuff
}

The switch can always compile to a simple look-up table that way.
January 04, 2008
Re: No more fall through in case statement?
bearophile wrote:
> Bill Baxter:
>> I'm no C# guy but that looks like a nice way to fix C's switch.
> 
> I think the C switch is broken in 2 or more ways, so I'd like to see D improve it. This is some code I have shown time ago:
> 
> import std.stdio: writefln;
> void main(string[] args) {
>   switch (args[1]) {
>     int x = 1; // NOT initialized?
>     case "1": writefln("1! x=", x); break;
>     case "2": writefln("2! x=", x); break;
>   }
> }

C++ fixed this some time in the last century, making the code
above ill-formed (diagnostic required) as it skips the initialization
of x.

(It's still UB in C99 so far as I know.)

-- James
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home