Thread overview | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 12, 2002 so what about switch() | ||||
---|---|---|---|---|
| ||||
Yeah, once again back to the old topic... Walter, are you going to provide some neater, more powerful, and less error-prone alternative to this #&!% C switch()? It's one of the most frequent sources of bugs, IMO, and the way it works is not intuitive and absolutely anti-C(D), in general. My suggestion of syntax: select (n) { case (0) foo(); case (1, 3, 7) { int m = foo(n); bar(n); } case (2, 4 .. 6, 9) bar(n); default throw new Error; } This should deal with most switch() problems: - no more break; only one case-block gets executed. Block statement is required if there are more then one statement in case (just like all other D constructs) - easy to check for several possible values and/or ranges What do you think of this? |
February 12, 2002 Re: so what about switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | Once break is no longer *required* in a switch, we can actually use break to break out of an enclosing loop, something I've wished for many times in the past. Sean "Pavel Minayev" <evilone@omen.ru> wrote in message news:a4ap6u$teg$1@digitaldaemon.com... > Yeah, once again back to the old topic... Walter, are you going > to provide some neater, more powerful, and less error-prone > alternative to this #&!% C switch()? It's one of the most frequent > sources of bugs, IMO, and the way it works is not intuitive > and absolutely anti-C(D), in general. > > My suggestion of syntax: > > select (n) > { > case (0) > foo(); > case (1, 3, 7) > { > int m = foo(n); > bar(n); > } > case (2, 4 .. 6, 9) > bar(n); > default > throw new Error; > } > > This should deal with most switch() problems: > > - no more break; only one case-block gets executed. Block statement > is required if there are more then one statement in case (just > like all other D constructs) > - easy to check for several possible values and/or ranges > > What do you think of this? > > |
February 12, 2002 Re: so what about switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | The difficulty I have is I haven't had problems with switch in my own code. I do like the idea of having multiple case values, though. The case range is a good idea, too. I don't want to change the fall through behavior, though. Is it really such a problem? "Pavel Minayev" <evilone@omen.ru> wrote in message news:a4ap6u$teg$1@digitaldaemon.com... > Yeah, once again back to the old topic... Walter, are you going > to provide some neater, more powerful, and less error-prone > alternative to this #&!% C switch()? It's one of the most frequent > sources of bugs, IMO, and the way it works is not intuitive > and absolutely anti-C(D), in general. > > My suggestion of syntax: > > select (n) > { > case (0) > foo(); > case (1, 3, 7) > { > int m = foo(n); > bar(n); > } > case (2, 4 .. 6, 9) > bar(n); > default > throw new Error; > } > > This should deal with most switch() problems: > > - no more break; only one case-block gets executed. Block statement > is required if there are more then one statement in case (just > like all other D constructs) > - easy to check for several possible values and/or ranges > > What do you think of this? > > |
February 12, 2002 Re: so what about switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean L. Palmer | "Sean L. Palmer" <spalmer@iname.com> wrote in message news:a4arei$ude$1@digitaldaemon.com... > Once break is no longer *required* in a switch, we can actually use break to > break out of an enclosing loop, something I've wished for many times in the > past. > > Sean There is, in D, a break label construct enabling breaking out of any lexically enclosing loop. |
February 12, 2002 Re: so what about switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | Language behaviour should default to the behaviour that is most commonly used and expected. Hence there should be an implicit break before each new case statement. The fall through behaviour of case can be omitted entirely with the logical justification being that the fall through is not part of the current case. Fall though should also be avoided in my view because doing so would facilitate converting the case statemement from a standard branch around block type of code, to a more efficient dispatch table type of code. In the syntax above, bracketing is redundant. The following syntax is superior selectcase (a) case 1,2,3 ... case 4,5,6 ... case 7,8,9 ... default ... end select Typically a compiler will comple the above code to. _case1: mov eax,a cmp eax,1 je l1a cmp eax,2 je l1a cmp eax,3 jne l1 l1a: <block1> jmp exit l1: cmp ax,4 je l2a cmp eax,5 je l2a cmp eax,6 jne l2 l2a: <block2> jmp exit l2: cmp eax,7 je l3a cmp eax,8 je l3a cmp eax,9 jne dflt l3a: <block3> jmp exit dflt: <block4> exit: * Without fallthrough the following code could be substituted.... This code will provide higher speed where the cases span a simple integer sequence by computing the jump address rather than performing multiple tests and jumps. In the pervious example the worst case execution hits the default block after 9 tests, 3 taken jumps and 6 aborted jumps. In the code below, it takes 2 unparallelable instructions and one jump. Other optimizations are possible. case1: mov ebx,a sub ebx,1 cmp ebx,9 jae dflt shl ebx,2 call [dispatch + bx] dflt: <block4> exit: * diapatch: &<block1> &<block2> &<block3> l1: <block1> ret l2: <block2> ret l3: <block3> ret I am not saying that D should provide this optimization. But D should be thoughtful that such an optimization can be performed. Mozilla contains a 10 page neted case statement in it's gif image compression parser. Madness. Walter <walter@digitalmars.com> wrote in message news:a4aril$ue9$1@digitaldaemon.com... > The difficulty I have is I haven't had problems with switch in my own code. > I do like the idea of having multiple case values, though. The case range is > a good idea, too. I don't want to change the fall through behavior, though. > Is it really such a problem? |
February 12, 2002 Re: so what about switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "Walter" <walter@digitalmars.com> wrote in message news:a4aril$ue9$1@digitaldaemon.com... > The difficulty I have is I haven't had problems with switch in my own code. It's the matter of experience, I believe. All amateur C programmers, especially those who came from other languages like BASIC or Pascal, with strict select-case statement, tend to forget to add the break at the end of case blocks. This is much like missing semicolons, but the latter is detected at compile-time, while one occasionaly missed break very often compiles silently and is then a source of hard-to- catch bugs. After some practice, though, you get used to break out of the cases - it took me about a month to polish my practical C skills (including switch-breaks) when I moved to C from Pascal. > I do like the idea of having multiple case values, though. The case range is > a good idea, too. I don't want to change the fall through behavior, though. > Is it really such a problem? First of all, I suggest to leave the switch() construct untouched (note that I proposed another keyword, select()), for some compatibility with C, and for those [really rare] cases when you really need the fall-through behaviour, like one in this piece of code (from WinD): case WM_LBUTTONDOWN: if (handleClicks) clicking = true; case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: mouseDown(new MouseEvent(this, wParam, lParam)); break; However, such code is typically hard to read, because you might assume there's a break statement where there isn't, or you might miss one that is really there... so the _recommended_ way would be to use select(), which is less prone for such errors. |
February 12, 2002 Re: so what about switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean L. Palmer | "Sean L. Palmer" <spalmer@iname.com> wrote in message news:a4arei$ude$1@digitaldaemon.com... > Once break is no longer *required* in a switch, we can actually use break to > break out of an enclosing loop, something I've wished for many times in the > past. Yes, I also had it in mind when proposing this idea. |
February 12, 2002 Re: so what about switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "Walter" <walter@digitalmars.com> wrote in message news:a4arl2$ueu$1@digitaldaemon.com... > There is, in D, a break label construct enabling breaking out of any lexically enclosing loop. True. But labels and goto (or break & continue w/label) make code somewhat harder to read - because you have to find that label to follow the execution flow of the program. If you're lucky enough to mess with the code written by one of those holy guys that use strict formatting rules (like me =)), you have a chance to see it easily: while(true) { switch() { ... break Out; .. } } Out: ... However, it's so easy to write this code in such a way you'll spend several minutes trying to find that damn Out in a 10-screen function listing. Not the most productive way to spend your time, it is. =) |
February 12, 2002 Re: so what about switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | I really think that this is a Good Idea...but that we do need a continuation block of some sort. My favorite (of what's been proposed here) was "goto case": select(n) { case(0) foo(); case(1,3,7) { int m = foo(n); goto case(2); } case(2,4..6,9) bar(n); default throw new Error; } -- The Villagers are Online! http://villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ] |
February 12, 2002 Re: so what about switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | People have also talked about switches on strings or other types. Frankly, I think that switches on arbitrary types is good, but switches on strings (i.e. arrays of chars and wchars) is almost "absolutely necessary". Trouble is, if you select() on an array, it's kind of ambiguous whether your're comparing the arrays (do the point to the same region and have the same length) or are you comparing the strings (would strcmp() return 0). I think that the default behavior should be the latter...but that there should be a language construct for the former. Maybe, like in setting arrays, we use the [] to tell the difference: char string[] = ...; select(string) { ... // compares arrays } select(string[]) { ... // compares array contents (i.e. the string value) } -- The Villagers are Online! http://villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ] |
Copyright © 1999-2021 by the D Language Foundation