Thread overview | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
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? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Leonard Dahlmann | 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? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Carlos Santander | 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? | ||||
---|---|---|---|---|
| ||||
Posted in reply to S. | 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? | ||||
---|---|---|---|---|
| ||||
Posted in reply to S. | 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? | ||||
---|---|---|---|---|
| ||||
Posted in reply to S. | 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? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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
|
Copyright © 1999-2021 by the D Language Foundation