digitalmars.D - while(...){ ... }else ...
- Jens Bauer (53/53) Jan 18 2015 I've sometimes wished for a while ... else combination in C.
- MattCoder (23/24) Jan 18 2015 Maybe I misunderstood your question, but what you think about
- Jens Bauer (17/20) Jan 18 2015 ... It's close, but the result would be different.
- MattCoder (29/36) Jan 18 2015 Alright I see the purpose about: "while(){}else(){}", but
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (13/13) Jan 18 2015 Unfortunately, this would break existing code:
- Jens Bauer (13/14) Jan 18 2015 That is absolutely correct. Good catch. I did not think of that
- Andrei Alexandrescu (2/18) Jan 18 2015 The short answer is we are not considering such a feature. Thanks.
- ketmar via Digitalmars-d (6/24) Jan 18 2015 it will introduce a new keyword, and it will break any code which using
- Jens Bauer (8/15) Jan 18 2015 That's OK with me. I'm not discouraged. Now I no longer have to
- ketmar via Digitalmars-d (5/7) Jan 18 2015 sure, you're welcome! this one is not so good, but another one may be
- Jens Bauer (55/55) Jan 18 2015 I'd like to give an example on a different use of the same
- ketmar via Digitalmars-d (14/38) Jan 18 2015 first sample is just a bad code, but second sample is a kind of cypher.
- deadalnix (3/16) Jan 18 2015 Compiler have simplification of CFG passes that makes this
I've sometimes wished for a while ... else combination in C. -But I never got around to proposing my suggestion to whoever or whatever committee is in charge of the C language. But since D is a language that has much more freedom regarding implementation, I'd like to suggest it here. :) This is my usual code: if(c >= '0' && c <= '9') { /* number */ while(c >= '0' && c <= '9') { c = *s++; ... do something with c ... } } else if((c >= 'A' && c <= 'Z') || (c >='a' && c <= 'z') || c == '_') { /* token */ while((c >= 'A' && c <= 'Z') || (c >='a' && c <= 'z') || c == '_') { c = *s++; } } else if(debug) { /* error */ } ... The arguments for 'if' and 'while' are the same, and the initial test could be reduced to a single test instead of multiple tests... while(c >= '0' && c <= '9') { /* number */ c = *s++; ... do something with c ... } else while((c >= 'A' && c <= 'Z') || (c >='a' && c <= 'z') || c == '_') { /* token */ c = *s++; } else if(debug) { /* error */ } ... Ah, much more readable. This makes it possible to repeat actions, in case a statement is true, generalizing the while statement slightly. Thus... If we for instance enter the first while(...), then we will not enter any of the 'else' statements.
Jan 18 2015
On Sunday, 18 January 2015 at 15:52:24 UTC, Jens Bauer wrote:... Ah, much more readable.Maybe I misunderstood your question, but what you think about this way: while(1){ if(c >= '0' && c <= '9') { /* number */ c = *s++; ... do something with c ... } else if ((c >= 'A' && c <= 'Z') || (c >='a' && c <= 'z') || c == '_') { /* token */ c = *s++; } else if(debug) { /* error */ break; } } Matheus.
Jan 18 2015
On Sunday, 18 January 2015 at 16:03:24 UTC, MattCoder wrote:On Sunday, 18 January 2015 at 15:52:24 UTC, Jens Bauer wrote: Maybe I misunderstood your question, but what you think about this way:... It's close, but the result would be different. The while is a combined if+while, where the first test of the while would be the 'if'. In the while(1) example, the character 'c' would perhaps be a number the first time. On the second iteration, the character would be allowed to be a letter. However, in the original 'proposal', the loops would be 'tighter'; the kind would be found first, and then the 'width' of that kind second, and when the end of the kind was reached, the while-block would be exited. So in other words: First check: Is it a number; if so, get the entire number... If not, try the second check: is it a token; if so, get the entire token, otherwise let us know that it's something unknown (but only if we're debugging).
Jan 18 2015
On Sunday, 18 January 2015 at 22:54:16 UTC, Jens Bauer wrote:On Sunday, 18 January 2015 at 16:03:24 UTC, MattCoder wrote:Alright I see the purpose about: "while(){}else(){}", but unfortunately D doesn't have this. Anyway looking at your first post, I'd like to suggest a way to improve your code: /* Create a "type check" function/method... you named it returning a defined type */ import std.string; type checkType(sometype s){ if(isNumeric(s)){ return TYPE_NUMBER; } // Check using regex for A..Z, a..z and '_' return TYPE_TOKEN; return TYPE_UNDEFINED; } // And then somewhere in your code you could do this: ... { switch(checkType(s)){ case TYPE_NUMBER : doNumberThing(s); break; case TYPE_TOKEN : doTokenThing(s); break; default : checkDebug(); } } It's not what you proposed earlier, but I think it can make things easier. Matheus.On Sunday, 18 January 2015 at 15:52:24 UTC, Jens Bauer wrote:... First check: Is it a number; if so, get the entire number... If not, try the second check: is it a token; if so, get the entire token, otherwise let us know that it's something unknown (but only if we're debugging).
Jan 18 2015
Unfortunately, this would break existing code: if(some_condition) while(some_other_condition) { // ... } else // ... Currently, the `else` branch belongs to the `if`; with your proposal, it would belong to the `while`. An `else` always attaches to the closest construct where it can be accepted; AFAICS, this cannot be changed without making the language grammar context-sensitive (it would require parsing `while` inside an `if` differently from other `while`s).
Jan 18 2015
On Sunday, 18 January 2015 at 18:16:47 UTC, Marc Schütz wrote:Unfortunately, this would break existing code:That is absolutely correct. Good catch. I did not think of that particular case. However... What if the 'else', which "belongs" to while, is named differently, for instance ... while(expression1) { } otherwise if(expression2) { } I know otherwise is a longer word, but it would not clash with existing code.
Jan 18 2015
"Jens Bauer" <doctor who.no> wrote:On Sunday, 18 January 2015 at 18:16:47 UTC, Marc Schütz wrote:The short answer is we are not considering such a feature. Thanks.Unfortunately, this would break existing code:That is absolutely correct. Good catch. I did not think of that particular case. However... What if the 'else', which "belongs" to while, is named differently, for instance ... while(expression1) { } otherwise if(expression2) { } I know otherwise is a longer word, but it would not clash with existing code.
Jan 18 2015
On Sun, 18 Jan 2015 22:56:23 +0000 Jens Bauer via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Sunday, 18 January 2015 at 18:16:47 UTC, Marc Sch=C3=BCtz wrote:it will introduce a new keyword, and it will break any code which using "otherwise" as identifier. as far as i can tell this (introducing new keyword) is one of the hardest thing to do, 'cause Walter will reject it without second thought (and he will be perfectly right).Unfortunately, this would break existing code:=20 That is absolutely correct. Good catch. I did not think of that=20 particular case. =20 However... What if the 'else', which "belongs" to while, is named=20 differently, for instance ... =20 while(expression1) { } otherwise if(expression2) { } =20 I know otherwise is a longer word, but it would not clash with=20 existing code.
Jan 18 2015
On Sunday, 18 January 2015 at 23:06:27 UTC, ketmar via Digitalmars-d wrote:it will introduce a new keyword, and it will break any code which using "otherwise" as identifier. as far as i can tell this (introducing new keyword) is one of the hardest thing to do, 'cause Walter will reject it without second thought (and he will be perfectly right).That's OK with me. I'm not discouraged. Now I no longer have to go and think about this. I'd rather show someone the idea and getting it rejected, than keeping it to myself and often regret that I never said anything. -A rejection will not stop me from making another proposal, though - in fact, I do have one more. ;)
Jan 18 2015
On Sun, 18 Jan 2015 23:20:43 +0000 Jens Bauer via Digitalmars-d <digitalmars-d puremagic.com> wrote:-A rejection will not stop me from making another proposal,=20 though - in fact, I do have one more. ;)sure, you're welcome! this one is not so good, but another one may be brilliant. and even if it will not be so brilliant... you always can make a third one. and fourth. and so on. ;-)
Jan 18 2015
I'd like to give an example on a different use of the same feature: while(length--) { *d++ = *s++; } if(length == -1) /* the programmer will need to know the value of length here. */ { /* handle case where length was exactly 0, it's now -1 */ } would become: while(length--) { *d++ = *s++; } otherwise { /* handle case where length was exactly 0, it's now -1 */ } --- A pseudo-assembly language version of a normal while-loop: bra wstart /* this usually cost (something like) a clock-cycle to start */ while: copy.b s+,d+ wstart: bcc while wend: --- Different version of the above: bcs wend while: copy.b s+,d+ bcc while wend: --- A pseudo-assembly language version of the 'otherwise' while-loop: bcs otherwise while: copy.b s+,d+ bcc while bra wend otherwise: /* handle zero-length */ wend: -These are not real good examples, though. However, they do show that the compiler would know that it can safely optimize the expression-test, and almost for free get the 'otherwise', which would cost only little extra CPU-time.
Jan 18 2015
On Sun, 18 Jan 2015 23:16:11 +0000 Jens Bauer via Digitalmars-d <digitalmars-d puremagic.com> wrote:I'd like to give an example on a different use of the same=20 feature: =20 while(length--) { *d++ =3D *s++; } if(length =3D=3D -1) /* the programmer will need to know the value=20 of length here. */ { /* handle case where length was exactly 0, it's now -1 */ } =20 would become: =20 while(length--) { *d++ =3D *s++; } otherwise { /* handle case where length was exactly 0, it's now -1 */ } =20first sample is just a bad code, but second sample is a kind of cypher. there is no sense in doing such microoptimisations, as decent modern compiler is able to do dataflow analysis and cse. and both samples are bad, 'cause they violates the rule "check first, then process". did you profile your code and found that such loops are real bottlenecks? i bet they aren't. yet they less readable than clearly spelled preconditions. this is microoptimisation in the sake of microoptimisation, it wins almost nothing and hurts code readability. all in all it's one of that things that looks nice, but makes more problems than they are able to solve. that's why language design is hard: nicely looking features can have many unforseen consequences. ;-)
Jan 18 2015
On Sunday, 18 January 2015 at 18:16:47 UTC, Marc Schütz wrote:Unfortunately, this would break existing code: if(some_condition) while(some_other_condition) { // ... } else // ... Currently, the `else` branch belongs to the `if`; with your proposal, it would belong to the `while`. An `else` always attaches to the closest construct where it can be accepted; AFAICS, this cannot be changed without making the language grammar context-sensitive (it would require parsing `while` inside an `if` differently from other `while`s).Compiler have simplification of CFG passes that makes this feature irrelevant in practice.
Jan 18 2015