February 12, 2002 Re: so what about switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | LOL Hey Walter, thanks for the work so far. :) -- The Villagers are Online! 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 14, 2002 Power switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | "Pavel Minayev" <evilone@omen.ru> wrote in 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()? The most practical and flexible loop of all programming languages is the "C++" for loop. None laguage has its power and simplicity. But the switch statement is not so good. Bellow some suggestion (or resume of someone) to improve the "multiple case statement" giving for it more power. 1. As commented in anothers messages in this thread, the "break" fallthrough is error prone and is not the default option for average cases in code. Stripping it brings some advantages IMHO: o The typing is reduced o The reading is improved mainly in large quantity of cases o The break could be used in loops without problems. o Many novice and some "hard to debug" errors could be prevented. o The syntax will follow anothers D statements syntax. The fallthrough case could be emulated, as Russ Lewis suggests, with the goto, without problem. The sintax will change something: for(;;) { ... switch(x){ case 1: break; case 2: { doSomething(); goto case_3; } case 3: { doAnotherthing() } default: RaiseMyException(); } } 2. There are three keywords for switch statement: "switch", "case" and "default". Once the break is out, there are no need of case keyword. And the default keyword could be replaced by another keyword in language: switch(x){ 1, 2, 3 : sigle_line_statement(); 4 : { multi_line_statement_1(); multi_line_statement_2(); multi_line_statement_3(); } else : another_statement(); } With this the keywords case and default dont are needed. I know some redundancy is good but I think the parser (yacc) dont will find problem because al identifiers have keywords delimitanting. Some persons dont like the keyword switch too and prefer "case" or "select" or "option". They have a more significant meaning !? 3. In some languages, the diferent cases must be only integral types. The D already allow using string as case for use. But you need use only constant types. This is made thus because choosed implementation is a jump table or some similar. But this is very restricting. Theare no reason for a modern compiler dont allow variables, expression, function calls or ranges to be a case option. Consider the following: o Many times the programmer will write nesteds if statements because they could not use expressions as "switch cases": if (x = a) { ... } else if ((x = b) or (x = c*3)) { ... } else if (x = get_old_x()) { ... } else if ((x >= 10) and (x =< 20)){ ... } this could be better writed as: switch(x){ a: { ... } b, c * 3 : { ... } get_old_x(): { ... } 10..20 : { ... } } Simpler and clearer IMHO. o The limitation is not give by sintax or semantic but by the compiler implementation. Generally the limitations of switch, case, select are decisions made in language definion because simplify something the implementation. But I think this will not add considerable bloat to a language. o For tradicional switch statement generally are a simple optimization like a jump table, or a hash table in case of strings. But nothing prevents the compiler of making this optimizations when possible. And there are a new door open for new optimizations discovered. The compiler also can mix the optimizations, when are not only same type constants involved. 4. The order of comparation must not follow the topbottom order necessarily: switch(y){ slow_function(): { ... } 1, 3, 4 : { ... } } If is needed precedence, the programmer could use the default argument : switch(y){ slow_function(): { ... } 1, 3, 4 : { ... } else: switch(y){ another_func() :{ ... } } } With this the compiler could use optimize the comparisons choose the best order in compile time. Until the optimization is not implemented or when is not possible to guess the best order, the compiler will follow the topbottom rule. IMHO, this solution will improved the switch statement and allow for the compiler have more power when optimizing the code. Comments, sugestion, Yes, No ? |
February 15, 2002 Re: so what about switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | Walter wrote: > 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? > I agree - if we are aiming for ex C programmers to migrate to D then we really need the old syntax to either look the same and act the same or look different and act in a new way. How about a varient of Pavel's otherwise good suggestion switch ( variable ) { case ( 1,2,3 ): doCode(); case ( 4,5..8 ): /* fall through */ doMoreCode(); when ( 12..17 ): /* auto break - like Ada/VHDL */ doOtherCode(); when others: /* or case others for fall through */ throw new Error; } these ideas are mosly from VHDL which does not support fall though, but mixed with C syntax to give a more consistant feel. (and C default is just plain nasty, while 'when others' / 'case others' is both clearer in meaning and plainer in use). The colons could be optional as they do not really appear to fit with the rest of C / D, or could be interchangable with semi-colon. The brackets probably should also be optional (but then a terminator ':' or ';' would be needed) PS: does '12..17' mean '12 <= x <= 17' or '12 <= x < 17' ? whould '17..12' produce an error or become '17 >= x >= 12' or '17 >= x > 12' ? > "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 15, 2002 Re: Power switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to Juarez Rudsatz | Juarez Rudsatz wrote: > "Pavel Minayev" <evilone@omen.ru> wrote in 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()? > > The most practical and flexible loop of all programming languages is > the "C++" for loop. None laguage has its power and simplicity. But the > switch statement is not so good. Bellow some suggestion (or resume of > someone) to improve the "multiple case statement" giving for it more > power. > > 1. As commented in anothers messages in this thread, the "break" > fallthrough is error prone and is not the default option for average cases > in code. Stripping it brings some advantages IMHO: > o The typing is reduced > o The reading is improved mainly in large quantity of cases > o The break could be used in loops without problems. > o Many novice and some "hard to debug" errors could be prevented. > o The syntax will follow anothers D statements syntax. I would advocate using a new keyword 'when' to effectively alias to 'break; case ' (I do this using '#define when break; case' if using C, though I admit to getting the idea from Ada/VHDL - and it does give some problems (ie. have to use case at start, default falls though), still it is better than missing a break; especially with the C I write!) Maybe 'else' could be used as 'default' without fallthrough? > The fallthrough case could be emulated, as Russ Lewis suggests, with the goto, without problem. The sintax will change something: > > for(;;) { > ... > switch(x){ > case 1: break; > case 2: { > doSomething(); > goto case_3; > } > case 3: { > doAnotherthing() > } > default: > RaiseMyException(); > } > } goto case_3: this is not good what if 'case "hello world":' is supported continue (as suggested earlier) would be better if you are going to run with this option <NITPICK> besides if this code is entered with x=1 it does an infinate loop </NITPICK> > 2. There are three keywords for switch statement: "switch", "case" and "default". Once the break is out, there are no need of case keyword. And the default keyword could be replaced by another keyword in language: > > switch(x){ > 1, 2, 3 : sigle_line_statement(); > 4 : { > multi_line_statement_1(); > multi_line_statement_2(); > multi_line_statement_3(); > } > else : another_statement(); > } yes - getting rid of 'default' is a good idea. > With this the keywords case and default dont are needed. I know some > redundancy is good but I think the parser (yacc) dont will find problem > because al identifiers have keywords delimitanting. > Some persons dont like the keyword switch too and prefer "case" or > "select" or "option". They have a more significant meaning !? yes - though it does not really matter, keeping switch will be just as good > 3. In some languages, the diferent cases must be only integral types. The > D already allow using string as case for use. But you need use only > constant types. This is made thus because choosed implementation is a jump > table or some similar. But this is very restricting. Theare no reason for > a modern compiler dont allow variables, expression, function calls or > ranges to be a case option. Consider the following: > o Many times the programmer will write nesteds if statements because > they could not use expressions as "switch cases": > if (x = a) { > ... > } > else > if ((x = b) or (x = c*3)) { > ... > } > else > if (x = get_old_x()) { > ... > } > else > if ((x >= 10) and (x =< 20)){ > ... > } > this could be better writed as: > > switch(x){ > a: { > ... > } > b, c * 3 : { > ... > } > get_old_x(): { > ... > } > 10..20 : { > ... > } > } > > Simpler and clearer IMHO. I think ELSIF would be better ie. (using your style) if (x = a) { ... } elsif ((x = b) or (x = c*3)) { ... } elsif(x = get_old_x()) { ... } elsif ((x >= 10) and (x =< 20)){ ... } > o The limitation is not give by sintax or semantic but by the compiler implementation. Generally the limitations of switch, case, select are decisions made in language definion because simplify something the implementation. But I think this will not add considerable bloat to a language. I would advise using switch to compare against constants and if / elsif / else for more complex expressions. This should both make the language less complex, simplify implementation and not loose and functionality (compared to your suggestion). [Walter - are we going to get an ELSIF construct in D - it does not appear to be in the specifications, though I think it would be fairly easy to add] > o For tradicional switch statement generally are a simple optimization like a jump table, or a hash table in case of strings. But nothing prevents the compiler of making this optimizations when possible. And there are a new door open for new optimizations discovered. The compiler also can mix the optimizations, when are not only same type constants involved. That adds otherwise unnecessary complexity to the compiler. > 4. The order of comparation must not follow the topbottom order necessarily: > > switch(y){ > slow_function(): { > ... > } > 1, 3, 4 : { > ... > } > } > > If is needed precedence, the programmer could use the default argument : > > switch(y){ > slow_function(): { > ... > } > 1, 3, 4 : { > ... > } > else: > switch(y){ > another_func() :{ > ... > } > } > } What is slow_function() has side effects (ie. setting a global variable) - then we are left with an implementation specific quection ie. does it execute? (assuming you have to check y == slow_function()). And also what would happen if say y = 3 and slow_function() returned 3 ? Seems a lot to remember for little real gain over the more common solution of ELSIF. > With this the compiler could use optimize the comparisons choose the best order in compile time. Until the optimization is not implemented or when is not possible to guess the best order, the compiler will follow the topbottom rule. > > IMHO, this solution will improved the switch statement and allow for the compiler have more power when optimizing the code. > > Comments, sugestion, Yes, No ? > Sorry, NO! ELSIF, although slightly more limited is far better for this less common construct, and also far easier to bolt onto an existing compiler (though I have not seen the D compiler source, so that may not be the case here). Otherwise a sequence of IF statements would do just as well, the only reason for having a specific ELSIF is for greater syntactic clarity. |
February 15, 2002 Re: Power switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to DrWhat? | "DrWhat?" <DrWhat@nospam.madscientist.co.uk> wrote in message news:a4hs5m$11vo$1@digitaldaemon.com... > [Walter - are we going to get an ELSIF construct in D - it does not > appear to be in the specifications, though I think it would be fairly > easy to add] Is it really needed? You can always use else if: if (a) ... else if (b) ... else if (c) ... I think it's just enough? |
February 15, 2002 Re: so what about switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to DrWhat? | "DrWhat?" <DrWhat@nospam.madscientist.co.uk> wrote in message news:a4hp3c$10tt$1@digitaldaemon.com... > switch ( variable ) > { case ( 1,2,3 ): > doCode(); > case ( 4,5..8 ): /* fall through */ > doMoreCode(); > when ( 12..17 ): /* auto break - like Ada/VHDL */ > doOtherCode(); > when others: /* or case others for fall through */ > throw new Error; > } > > these ideas are mosly from VHDL which does not support fall though, > but mixed with C syntax to give a more consistant feel. > (and C default is just plain nasty, while 'when others' / 'case others' is > both clearer in meaning and plainer in use). I suggested something like this, mixed old/new style, before (only I proposed the "on" keyword, not "when"). Seems fine as well. > The colons could be optional as they do not really appear to fit with > the rest of C / D, or could be interchangable with semi-colon. > The brackets probably should also be optional (but then a terminator > ':' or ';' would be needed) A colon after the case is unneeded if you have the brackets. We don't have it after if(), right? And the brackets are better be there - for consistency with all other constructs. > PS: does '12..17' mean '12 <= x <= 17' or '12 <= x < 17' ? I guess it should follow the syntax for array slices, to prevent confusion. So 12 <= x < 17. > whould '17..12' produce an error or become > '17 >= x >= 12' or '17 >= x > 12' ? I vote for error. Once again, an array slice like 17..12 is illegal in D. So making it illegal for switch() as well is a good idea, IMO. |
February 15, 2002 Re: Power switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | Pavel Minayev wrote:
> "DrWhat?" <DrWhat@nospam.madscientist.co.uk> wrote in message news:a4hs5m$11vo$1@digitaldaemon.com...
>
>> [Walter - are we going to get an ELSIF construct in D - it does not
>> appear to be in the specifications, though I think it would be fairly
>> easy to add]
>
> Is it really needed? You can always use else if:
>
> if (a)
> ...
> else if (b)
> ...
> else if (c)
> ...
>
> I think it's just enough?
Ok, you have convinced me, I though about this in the context of a
different language which enforces { ... } after a block statement,
though I say it should still be easy to implement using up another
keyword (to save two keypresses) on this less common construct
does not seem worth the effort.
Point conceeded.
C 2002/2/15
|
February 15, 2002 Re: Power switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to Juarez Rudsatz | Using a goto to emulate a fall though is a bad idea. First it begs abuse where programmers will use goto to jump around multiple times within a case statement. The result will be more difficult to manage than having a fallthrough as default. If fallthrough is needed (and I am not convinced that it is), it would be better to end the case block with a Fallthrough keyword. This way the programmer is constrained In fact allowing GOTO within a case statement is just a generally all round bad idea. Partucularly if the GOTO is allowed to jump out of the current case. As to optimizations, supporting GOTO's is also an inpediment. whereas a fallthrough is simply a secondary entry point to a comon function shared between the various cases. Juarez Rudsatz <juarez@correio.com> wrote in message news:Xns9115A04D7A983juarezcorreio@63.105.9.61... > o For tradicional switch statement generally are a simple optimization like a jump table, or a hash table in case of strings. But nothing prevents > the compiler of making this optimizations when possible. And there are a new door open for new optimizations discovered. The compiler also can mix the optimizations, when are not only same type constants involved. |
February 15, 2002 Re: Power switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to d | "d" <s_nudds@hotmail.com> wrote in message news:a4jde2$1q97$1@digitaldaemon.com... > As to optimizations, supporting GOTO's is also an inpediment. Not the way I do it. Internally, all control structures are translated to goto's before optimization anyway. All the optimizations work on a graph of basic blocks connected by edges (goto's). |
February 16, 2002 Re: Power switch() | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | That's good... goto is the most basic control flow instruction in all processors I know of anyway. At the assembly level you usually have call, goto, and goto-if-condition-holds. Makes sense for the compiler to work in those terms... it all works out to a graph anyway. I think most optimizing compilers these days don't have any problem with goto statements. Sean "Walter" <walter@digitalmars.com> wrote in message news:a4jfd5$1rar$3@digitaldaemon.com... > > "d" <s_nudds@hotmail.com> wrote in message news:a4jde2$1q97$1@digitaldaemon.com... > > As to optimizations, supporting GOTO's is also an inpediment. > > Not the way I do it. Internally, all control structures are translated to goto's before optimization anyway. All the optimizations work on a graph of > basic blocks connected by edges (goto's). |
Copyright © 1999-2021 by the D Language Foundation