[Issue 3699] Feature Request: while-else
https://issues.dlang.org/show_bug.cgi?id=3699 Andrei Alexandrescu and...@erdani.com changed: What|Removed |Added Version|unspecified |D2 --
Re: while(...){ ... }else ...
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.
Re: while(...){ ... }else ...
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.
while(...){ ... }else ...
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.
Re: while(...){ ... }else ...
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).
Re: while(...){ ... }else ...
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).
Re: while(...){ ... }else ...
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.
Re: while(...){ ... }else ...
Jens Bauer doc...@who.no wrote: 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. The short answer is we are not considering such a feature. Thanks.
Re: while(...){ ... }else ...
On Sun, 18 Jan 2015 22:56:23 + Jens Bauer via Digitalmars-d digitalmars-d@puremagic.com wrote: 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. 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). signature.asc Description: PGP signature
Re: while(...){ ... }else ...
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: sub length,#1 bcc while wend: --- Different version of the above: sub length,#1 bcs wend while: copy.b s+,d+ sub length,#1 bcc while wend: --- A pseudo-assembly language version of the 'otherwise' while-loop: sub length,#1 bcs otherwise while: copy.b s+,d+ sub length,#1 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.
Re: while(...){ ... }else ...
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. ;)
Re: while(...){ ... }else ...
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: 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). 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.
Re: while(...){ ... }else ...
On Sun, 18 Jan 2015 23:16:11 + Jens Bauer via Digitalmars-d digitalmars-d@puremagic.com wrote: 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 */ } first 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. ;-) signature.asc Description: PGP signature
Re: while(...){ ... }else ...
On Sun, 18 Jan 2015 23:20:43 + Jens Bauer via Digitalmars-d digitalmars-d@puremagic.com wrote: -A rejection will not stop me from making another proposal, 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. ;-) signature.asc Description: PGP signature
[Issue 3699] Feature Request: while-else
https://d.puremagic.com/issues/show_bug.cgi?id=3699 --- Comment #8 from Andrei Alexandrescu and...@erdani.com 2014-03-18 23:12:04 PDT --- Thanks for cleaning up the list! -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 3699] Feature Request: while-else
https://d.puremagic.com/issues/show_bug.cgi?id=3699 bearophile_h...@eml.cc changed: What|Removed |Added Status|RESOLVED|REOPENED CC||bearophile_h...@eml.cc Resolution|WONTFIX | --- Comment #9 from bearophile_h...@eml.cc 2014-03-19 05:36:12 PDT --- (In reply to comment #7) Four year old request. Can be discussed further on NG if required. There are bugs that sleep in bugzilla for years just because no one has time or desire to fix them, but they are still valid. I have plenty of similar bugs in bugzilla. So closing down an issue just for lack of fixes is not a good idea. And a Python-like else clause of while/for/foreach is nice. You can replace code like: bool ok = true; foreach (...) { ... if (cond) { ok = false; break; } } if (!ok) { ... } With: foreach (...) { ... if (cond) break; } else { ... } Reopened until we have a true decision. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 3699] Feature Request: while-else
https://d.puremagic.com/issues/show_bug.cgi?id=3699 Andrei Alexandrescu and...@erdani.com changed: What|Removed |Added Status|REOPENED|RESOLVED Resolution||WONTFIX --- Comment #10 from Andrei Alexandrescu and...@erdani.com 2014-03-19 08:55:27 PDT --- I don't think we can keep all proposals opened on the off chance one may be acted upon at some point. At some point we need to make a decision. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 3699] Feature Request: while-else
https://d.puremagic.com/issues/show_bug.cgi?id=3699 Infiltrator lt.infiltra...@gmail.com changed: What|Removed |Added Status|NEW |RESOLVED CC||lt.infiltra...@gmail.com Resolution||WONTFIX --- Comment #7 from Infiltrator lt.infiltra...@gmail.com 2014-03-18 22:22:06 PDT --- Four year old request. Can be discussed further on NG if required. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 3699] Feature Request: while-else
http://d.puremagic.com/issues/show_bug.cgi?id=3699 Don clugd...@yahoo.com.au changed: What|Removed |Added CC||clugd...@yahoo.com.au Severity|normal |enhancement -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 3699] Feature Request: while-else
http://d.puremagic.com/issues/show_bug.cgi?id=3699 --- Comment #6 from ibrahim YANIKLAR yanik...@gmail.com 2010-01-14 04:07:19 PST --- (In reply to comment #5) (In reply to comment #4) (In reply to comment #3) This fails to follow those guidelines, and introduces silent changes in behavior. Not silent, by giving a warning message. Warnings are not a defined part of the D Programming Language. (http://digitalmars.com/d/2.0/warnings.html) IOW, warnings are not an option. OK But we can solve this problem by several ways. If that creates inconsistencies, it will not be accepted. And the proposed solutions do. I think giving priority to 'if' about 'else's solves all inconsistencies between existing code and the new feature. Or the radical solution: 'otherwise' ... -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 3699] Feature Request: while-else
http://d.puremagic.com/issues/show_bug.cgi?id=3699 --- Comment #4 from ibrahim YANIKLAR yanik...@gmail.com 2010-01-13 04:16:19 PST --- (In reply to comment #3) This fails to follow those guidelines, and introduces silent changes in behavior. Not silent, by giving a warning message. But we can solve this problem by several ways. 1) by giving priority to if. Examples: if (c1) while (c2) stmt1 else stmt2 will behave like this: if (c1) { while (c2) stmt1 } else stmt2 -- while (c1) while (c2) stmt1 else stmt2 will behave like this: while (c1) { while (c2) stmt1 else stmt2 } (2) in addition to (1) it can be standardized by the rule: the outermost else is belonging to the outermost while. Then: while (c1) while (c2) stmt1 else stmt2 will behave like this: while (c1) { while (c2) stmt1 } else stmt2 (3) in addition to (1) this type of ambiguities (which 'while' 'else' belongs to) can be forbidden then this will give an error while (c1) while (c2) stmt1 else stmt2 (4) using otherwise statement instead of else while (c1) stmt1 otherwise stmt2 -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 3699] Feature Request: while-else
http://d.puremagic.com/issues/show_bug.cgi?id=3699 --- Comment #5 from Simen Kjaeraas simen.kja...@gmail.com 2010-01-13 10:39:31 PST --- (In reply to comment #4) (In reply to comment #3) This fails to follow those guidelines, and introduces silent changes in behavior. Not silent, by giving a warning message. Warnings are not a defined part of the D Programming Language. (http://digitalmars.com/d/2.0/warnings.html) IOW, warnings are not an option. But we can solve this problem by several ways. If that creates inconsistencies, it will not be accepted. And the proposed solutions do. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 3699] New: Feature Request: while-else
http://d.puremagic.com/issues/show_bug.cgi?id=3699 Summary: Feature Request: while-else Product: D Version: unspecified Platform: All OS/Version: All Status: NEW Severity: normal Priority: P2 Component: DMD AssignedTo: nob...@puremagic.com ReportedBy: yanik...@gmail.com --- Comment #0 from ibrahim YANIKLAR yanik...@gmail.com 2010-01-12 08:39:50 PST --- It would be nice to add a while-else statement to the language. while ( Expression1 ) ScopeStatement1 else ScopeStatement2 may act like that: if ( Expression1 ) do ScopeStatement1 while ( Expression1 ); else ScopeStatement2 or like that: bool entered = false; while ( Expression1 ) { entered = true; ScopeStatement1 } if (!entered) ScopeStatement2 two of them has some problems. First one is more efficient but you must write the same expression twice. The second is more readable but there is an extra declaration and an extra cost. while-else is more readable and more efficient. someone can want a python like while-else statement. using while-finally syntax would be more suitable for that. while ( ... ) { ... if ( ... ) break; ... } finally ScopeStatement3 ... if break occures the ScopeStatement3 is not executed else it is executed once. But I think it is not necessary because we can provide that by using a simple goto statement instead of break. while ( ... ) { ... if ( ... ) goto label; ... } ScopeStatement3 label: ... -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 3699] Feature Request: while-else
http://d.puremagic.com/issues/show_bug.cgi?id=3699 Andrei Alexandrescu and...@metalanguage.com changed: What|Removed |Added CC||and...@metalanguage.com --- Comment #1 from Andrei Alexandrescu and...@metalanguage.com 2010-01-12 09:19:33 PST --- What should this do? if (c1) while (c2) stmt1 else stmt2 And in particular, how would you reconcile existing code with the new feature? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 3699] Feature Request: while-else
http://d.puremagic.com/issues/show_bug.cgi?id=3699 --- Comment #2 from ibrahim YANIKLAR yanik...@gmail.com 2010-01-12 10:42:09 PST --- What should this do? if (c1) while (c2) stmt1 else stmt2 if (c1) { while (c2) stmt1 else stmt2 } It should do that of course. And in particular, how would you reconcile existing code with the new feature? In such situations the compiler can warn the developer, perhaps it can be bound to -w switch. General the developers uses this form: if (c1) { while (c2) stmt1 } else stmt2 instead of: if (c1) while (c2) stmt1 else stmt2 D2 is in alpha status, isn't it. I see some changes on D2 that breaks code. You should decide whether the new feature is important and necessary enough to accept the risk of code breaks or not. I usually feel the need for that feature. an example on fetching rows from db: while (row = query.nextRow()) writeln(row); else writeln(no row); It's really a nice feature. I think D should collect all the nice features itself. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 3699] Feature Request: while-else
http://d.puremagic.com/issues/show_bug.cgi?id=3699 Simen Kjaeraas simen.kja...@gmail.com changed: What|Removed |Added CC||simen.kja...@gmail.com --- Comment #3 from Simen Kjaeraas simen.kja...@gmail.com 2010-01-12 15:16:59 PST --- (In reply to comment #2) D2 is in alpha status, isn't it. I see some changes on D2 that breaks code. You should decide whether the new feature is important and necessary enough to accept the risk of code breaks or not. Yes. But an important goal of D has been the principle of least astonishment (for C programmers). That is, C code copied to D should either compile successfully, or fail spectacularly. This fails to follow those guidelines, and introduces silent changes in behavior. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---