digitalmars.D - Comma operator = broken design
- =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= (29/29) Dec 07 2011 Hi,
- Joshua Cearley (1/1) Dec 07 2011 It could be moved to use either the section character or one of the appl...
- Robert Jacques (11/39) Dec 07 2011 Take your pick:
- Nick Sabalausky (23/50) Dec 07 2011 That's a pretty weak counter-argument:
- Robert Jacques (8/33) Dec 07 2011 Yes, the poster was (in part) asking about where the comma operator came...
- Joshua Reusch (3/5) Dec 08 2011 If we use the comma operator only for tuples, there needn't to be a
- Robert Jacques (5/10) Dec 08 2011 Clever! However,
- Kagamin (3/9) Dec 08 2011 for(int x, y = 0 , 100; x < y ; x, y += 1,-1) { ... }
- Robert Jacques (5/17) Dec 09 2011 Here's how I understood it:
- Jonathan M Davis (11/33) Dec 09 2011 I'd _hate_ to be restricted to doing the same operation in the 3rd porti...
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (4/37) Dec 11 2011 Indeed, having the comma operator in for loops is perfectly normal; even...
- Robert Jacques (4/45) Dec 11 2011 A lot (all?) of for loop use cases seem to actually work in tuple form. ...
- Jonathan M Davis (10/16) Dec 11 2011 What if one of the expression's result is void?
- Robert Jacques (4/20) Dec 11 2011 Ah, thank you. I was observing that my standard for loop syntax actually...
- Adam Ruppe (18/21) Dec 07 2011 Aside from the compiler's implementation, one possible use
- Nick Sabalausky (4/25) Dec 07 2011 Don't know about JS, but D can solve the same problem with anon delegate...
- Timon Gehr (4/42) Dec 07 2011 I think Don said that DMD cannot currently inline any delegates. Imho
- Jonathan M Davis (11/57) Dec 07 2011 lazy doesn't get inlined for the same reason (since it's essentially usi...
- bcs (5/10) Dec 07 2011 IIRC the generated code argument was actually made with regards to the
- Don (7/17) Dec 08 2011 Worth noting that the comma operator inside the compiler is not the same...
- Dejan Lekic (2/4) Dec 08 2011 No offense, but I find it strange/funny that you even ask why! :)
- so (6/10) Dec 08 2011 Not sure if it is that relevant for D, but good point.
- Regan Heath (23/37) Dec 08 2011 It's kinda amusing that this thread appeared just as we had a case of th...
- so (5/11) Dec 08 2011 Not that related but my all time favorite is still:
- Dejan Lekic (1/3) Dec 08 2011 If "type" has the default initialiser, then what is the problem?
- so (14/18) Dec 08 2011 What does it do in both C and D context?
- Robert Jacques (2/21) Dec 08 2011 Actually, these statements don't violate the B-D rule. In C/C++ the valu...
- so (16/46) Dec 08 2011 I disagree. As you said while in C/C++ same thing gets assigned random
- Robert Jacques (4/52) Dec 08 2011 I totally agree, from a normal control flow perspective. But .init has m...
- so (15/17) Dec 08 2011 It was/is one of the defining points of D AFAIK.
- Robert Jacques (2/19) Dec 09 2011 Interesting point. I agree with D being a very pragmatic language (it's ...
- Timon Gehr (2/39) Dec 08 2011 Phobos would break, for example. And some of my code too.
- Don (3/50) Dec 09 2011 Are there any cases where you're using comma outside of for loops?
- Jonathan M Davis (10/12) Dec 09 2011 I'm sure that it would break code, but most people consider it bad pract...
- Timon Gehr (8/23) Dec 09 2011 It is confusing to people who don't know the language. It is a simple
- Regan Heath (11/33) Dec 09 2011 It's error prone in cases where you use it without realising, as in the ...
- Timon Gehr (21/58) Dec 09 2011 'most people' do not care about this discussion, so lets stop it. :o)
- Regan Heath (7/33) Dec 09 2011 Excellent.
- Timon Gehr (3/37) Dec 09 2011 Removing the comma operator makes my life harder. You don't want to do
- Regan Heath (8/22) Dec 09 2011 :p
- Piotr Szturmaj (9/17) Dec 09 2011 What about just not using comma operator? Yes, I know about keyboard
- Regan Heath (7/21) Dec 09 2011 True, but D has already turned a good number of those into errors. This...
- Tobias Pankrath (5/8) Dec 09 2011 It may not be error prone to write, but it is error prone to read, becau...
- Timon Gehr (3/11) Dec 09 2011 You always have to be careful when reading code.
- Jonathan M Davis (5/38) Dec 09 2011 In my experience, someone like you who uses the comma operator outside o...
- Timon Gehr (29/80) Dec 09 2011 These are the occurences of the comma operator in directory 'std':
- Regan Heath (6/41) Dec 09 2011 All of the above could be improved with the removal of the comma operato...
- bearophile (5/40) Dec 09 2011 It's ugly code worth fixing/rewriting. If I see something like that in p...
- Regan Heath (82/110) Dec 09 2011 Here is my /very/ quick re-write of each without looking at the context ...
- Timon Gehr (15/79) Dec 09 2011 This is blatant code duplication.
- Regan Heath (15/120) Dec 09 2011 What information? With context I could be more specific about what to d...
- Timon Gehr (23/148) Dec 09 2011 You can always grep the Phobos source to get context. Basically, you are...
- Regan Heath (15/111) Dec 09 2011 If using 'goto' is the 'correct' agreed upon style for phobos then, yes....
- Timon Gehr (4/117) Dec 09 2011 What you might be missing is that assert(false) is not compiled out in
- Regan Heath (6/52) Dec 09 2011 I was indeed missing that. I couldn't find anything about it on the
- Timon Gehr (2/53) Dec 09 2011 http://d-programming-language.org/expression.html#AssertExpression
- Regan Heath (5/18) Dec 12 2011 I found that :p .. but nothing about behaviour in release/debug/etc.
- bearophile (4/7) Dec 12 2011 It's a known little wart of D2. We discussed about it some time ago. I h...
- Timon Gehr (7/81) Dec 09 2011 The code was probably written that way to give an optimal implementation...
- Steven Schveighoffer (27/103) Dec 09 2011 goto in this case is acceptable. It's a goto case statement, which
- Jonathan M Davis (5/20) Dec 09 2011 Actually, that particular usage of the comma operator makes me almost wa...
- Derek (7/8) Dec 09 2011 OMG! What ever happened to the idea that source code is meant to AID
- Timon Gehr (3/8) Dec 09 2011 You are exaggerating.
- Kagamin (3/5) Dec 08 2011 Modern shells usually allow to use several keyboard layouts,
Hi, Consider this code: if (condition) foo(); else bar(), baz(); Notice the comma in the bar call. This will actually compile. Why? Because the program is really interpreted as: if (condition) { foo(); } else { bar(); baz(); } This is, honestly, ridiculous. On most European keyboard layouts, comma is on the same key as semicolon. This means that a typo such as the above can lead to an incorrect (but compiling) program easily, rather than a compile-time error. I really do not see the value in allowing such syntax in the first place. I've been told that one argument was that generated code might use it, but I have no idea why it would be needed. Furthermore, this operator makes it very hard to introduce Python-style tuples in the language. Why is this operator still kept around? - Alex
Dec 07 2011
It could be moved to use either the section character or one of the application-specific unicode points reserved for internal use by whatever an application wants. This would eliminate confusing typing and, if using this for generated code, the generator can easily reference it by unicode ID when constructing the strings.
Dec 07 2011
On Wed, 07 Dec 2011 11:49:33 -0500, Alex Rønne Petersen <xtzgzorex gmail.com> wrote:Hi, Consider this code: if (condition) foo(); else bar(), baz(); Notice the comma in the bar call. This will actually compile. Why? Because the program is really interpreted as: if (condition) { foo(); } else { bar(); baz(); } This is, honestly, ridiculous. On most European keyboard layouts, comma is on the same key as semicolon. This means that a typo such as the above can lead to an incorrect (but compiling) program easily, rather than a compile-time error. I really do not see the value in allowing such syntax in the first place. I've been told that one argument was that generated code might use it, but I have no idea why it would be needed. Furthermore, this operator makes it very hard to introduce Python-style tuples in the language. Why is this operator still kept around?Take your pick: 1) So that legacy B/C/C++/D1/etc code can be trivially ported to D1/D2. 2) The comma operator is heavily used in regular old for loops. 3) It is frequently used internally by the compiler to effect syntactic lowerings. A decent portion of D's syntax is not transformed directly to instructions; instead it is converted to simpler code which is in turn processed. Technically the compiler doesn't need ',' in the language to do this. 4) D has a policy of 'If C/C++ code compiles in D without error, it must have the same syntactic meaning as in C.' So even if we remove the comma operator, we might not get comma-style tuples. (I don't know if anyone has looked at this issue in depth) 5) The comma and semicolon are on different keys on US style keyboards. 6) It is trivial to change your keyboard layout (I've hotkeyed Greek for fast math symbols) 7) We are trying to stabilize the language, so massive code-breaks are frowned upon. Personally, I think real tuples outweigh the comma-operator, but real tuples don't necessarily need the ',' (we could use '..' or something else instead) and removing comma-expressions isn't without its problems. P.S. I was going to suggest testing/looking into issue 4, but a quick test in D suggests that there are valid ',' and '(,)' style expressions in C/C++ that would remain valid in D with comma-tuples.
Dec 07 2011
"Robert Jacques" <sandford jhu.edu> wrote in message news:op.v54q04vd26stm6 sandford.myhome.westell.com...On Wed, 07 Dec 2011 11:49:33 -0500, Alex Rønne Petersen <xtzgzorex gmail.com> wrote:That's a pretty weak counter-argument: A. I'd think a lot of C/C++ code can't be trivially ported to D anyway. B. "B", seriously? ;) C. Being able to link to C/C++ makes it less likely to need to port C/C++ code anyway. D. Outside of for loops (special-case-able), comma operator is rarely used in C/C++/D. E. Even among actual uses of the comma operator, I think it'd be rare (if even possible) to have a use of it that isn't trivially convertable to non-comma.Why is this operator still kept around?Take your pick: 1) So that legacy B/C/C++/D1/etc code can be trivially ported to D1/D2.2) The comma operator is heavily used in regular old for loops.That can be special cased.3) It is frequently used internally by the compiler to effect syntactic lowerings. A decent portion of D's syntax is not transformed directly to instructions; instead it is converted to simpler code which is in turn processed. Technically the compiler doesn't need ',' in the language to do this.Like you're saying, it can exist in the compiler's internal AST without having to exist in the parser.4) D has a policy of 'If C/C++ code compiles in D without error, it must have the same syntactic meaning as in C.' So even if we remove the comma operator, we might not get comma-style tuples. (I don't know if anyone has looked at this issue in depth)Meh, I still think it would be better to allow such situations on occasion and just provide a "--c-lint" switch to warn (or error) on any such code. Porting C/C++ to D is a much smaller use case than writing/maintaining D. I don't think it's a good idea to hamper the langauge for the sake of such an edge case when it's just as possible to simply handle that scenario with a special tool/switch. But I guess I'm outvoted by Walter on that :(5) The comma and semicolon are on different keys on US style keyboards. 6) It is trivial to change your keyboard layout (I've hotkeyed Greek for fast math symbols)Those are very weak counter-arguments.7) We are trying to stabilize the language, so massive code-breaks are frowned upon.Poo ;(Personally, I think real tuples outweigh the comma-operator, but real tuples don't necessarily need the ',' (we could use '..' or something else instead) and removing comma-expressions isn't without its problems. P.S. I was going to suggest testing/looking into issue 4, but a quick test in D suggests that there are valid ',' and '(,)' style expressions in C/C++ that would remain valid in D with comma-tuples.
Dec 07 2011
On Wed, 07 Dec 2011 13:19:31 -0500, Nick Sabalausky <a a.a> wrote:"Robert Jacques" <sandford jhu.edu> wrote in message news:op.v54q04vd26stm6 sandford.myhome.westell.com...That statement implies that there is a lot of code that can be trivially ported to D.On Wed, 07 Dec 2011 11:49:33 -0500, Alex Rønne Petersen <xtzgzorex gmail.com> wrote:That's a pretty weak counter-argument: A. I'd think a lot of C/C++ code can't be trivially ported to D anyway.Why is this operator still kept around?Take your pick: 1) So that legacy B/C/C++/D1/etc code can be trivially ported to D1/D2.B. "B", seriously? ;)Yes, the poster was (in part) asking about where the comma operator came from. C did a lot of stupid things to be portable with B and we have all inherited that legacy.C. Being able to link to C/C++ makes it less likely to need to port C/C++ code anyway.Sure, for code that's in reasonably complete libraries that full fill your use cases and are supported by someone else. That's not always the case.D. Outside of for loops (special-case-able), comma operator is rarely used in C/C++/D.Special casing is a big and dangerous hammer. Generally, it introduces extra work for the compiler and cognitive load for the programmer. Now, we have used special casing to detect common errors to great effect, but these don't add cognitive load to the programmer.E. Even among actual uses of the comma operator, I think it'd be rare (if even possible) to have a use of it that isn't trivially convertable to non-comma.True, but that still implies extra work on the part of the programmer.Ahem. So are you suggesting that (a,b) means a tuple everywhere but in a for loop, where it is used to separate two statements?2) The comma operator is heavily used in regular old for loops.That can be special cased.I don't disagree, but the poster's original argument was (essentially) that EU keyboards put ; and , on the same key, so it was easy to mistype between the two. I was just suggesting that maybe the poster might want to fix their keyboard before trying to 'fix' the language.5) The comma and semicolon are on different keys on US style keyboards. 6) It is trivial to change your keyboard layout (I've hotkeyed Greek for fast math symbols)Those are very weak counter-arguments.
Dec 07 2011
Ahem. So are you suggesting that (a,b) means a tuple everywhere but in a for loop, where it is used to separate two statements?If we use the comma operator only for tuples, there needn't to be a special case for loops: for(x, y = 0 , 100; x < y ; x, y += 1,-1) { ... }
Dec 08 2011
On Thu, 08 Dec 2011 12:18:56 -0500, Joshua Reusch <yoschi arkandos.de> wrote:>Clever! However, 1) Showing that the trivial example can be expressed with tuples is a good first step. The next step is to go after some of the advanced comma usages. i.e. What's the limitations of this approach? When does it break down? 2) As per the current tuple proposals, the above is a horrendous performance sink. Granted, more tuple awareness in the compiler might fix the problem, but that awareness is more than what's in the current tuple proposals.Ahem. So are you suggesting that (a,b) means a tuple everywhere but in a for loop, where it is used to separate two statements?If we use the comma operator only for tuples, there needn't to be a special case for loops: for(x, y = 0 , 100; x < y ; x, y += 1,-1) { ... }
Dec 08 2011
On Thursday, 8 December 2011 at 17:18:57 UTC, Joshua Reusch wrote:for(int x, y = 0 , 100; x < y ; x, y += 1,-1) { ... } ?Ahem. So are you suggesting that (a,b) means a tuple everywhere but in a for loop, where it is used to separate two statements?If we use the comma operator only for tuples, there needn't to be a special case for loops: for(x, y = 0 , 100; x < y ; x, y += 1,-1) { ... }
Dec 08 2011
On Fri, 09 Dec 2011 01:20:45 -0500, Kagamin <spam here.lot> wrote:On Thursday, 8 December 2011 at 17:18:57 UTC, Joshua Reusch wrote:Here's how I understood it: int x,y; // Defined somewhere in the code above for( (x,y) = (0,100); x < y ; (x,y) += (1,-1) ) { ... } So you have variable capture, assignment and add-assign happening.for(int x, y = 0 , 100; x < y ; x, y += 1,-1) { ... } ?Ahem. So are you suggesting that (a,b) means a tuple everywhere but in a for loop, where it is used to separate two statements?If we use the comma operator only for tuples, there needn't to be a special case for loops: for(x, y = 0 , 100; x < y ; x, y += 1,-1) { ... }
Dec 09 2011
On Friday, December 09, 2011 20:18:36 Robert Jacques wrote:On Fri, 09 Dec 2011 01:20:45 -0500, Kagamin <spam here.lot> wrote:I'd _hate_ to be restricted to doing the same operation in the 3rd portion of a for loop for all of its parts. The comma operator is _perfect_ for there, and I wouldn't want to see its behavior changed there regardless. e.g. things like this should continue to be perfectly possible and legal for(; cond; ++x, y *= 2) {} Tuples do _not_ have the proper semantics for a for loop. It would be one thing for the comma operator were to go away in the general case, but it would be horrible IMHO for its behavior to be changed in for loops - be it in an effort to make it act like it's using tuples or any other reason. - Jonathan M DavisOn Thursday, 8 December 2011 at 17:18:57 UTC, Joshua Reusch wrote:Here's how I understood it: int x,y; // Defined somewhere in the code above for( (x,y) = (0,100); x < y ; (x,y) += (1,-1) ) { ... } So you have variable capture, assignment and add-assign happening.for(int x, y = 0 , 100; x < y ; x, y += 1,-1) { ... } ?Ahem. So are you suggesting that (a,b) means a tuple everywhere but in a for loop, where it is used to separate two statements?If we use the comma operator only for tuples, there needn't to be a special case for loops: for(x, y = 0 , 100; x < y ; x, y += 1,-1) { ... }
Dec 09 2011
On 10-12-2011 02:39, Jonathan M Davis wrote:On Friday, December 09, 2011 20:18:36 Robert Jacques wrote:Indeed, having the comma operator in for loops is perfectly normal; even - AlexOn Fri, 09 Dec 2011 01:20:45 -0500, Kagamin<spam here.lot> wrote:I'd _hate_ to be restricted to doing the same operation in the 3rd portion of a for loop for all of its parts. The comma operator is _perfect_ for there, and I wouldn't want to see its behavior changed there regardless. e.g. things like this should continue to be perfectly possible and legal for(; cond; ++x, y *= 2) {} Tuples do _not_ have the proper semantics for a for loop. It would be one thing for the comma operator were to go away in the general case, but it would be horrible IMHO for its behavior to be changed in for loops - be it in an effort to make it act like it's using tuples or any other reason. - Jonathan M DavisOn Thursday, 8 December 2011 at 17:18:57 UTC, Joshua Reusch wrote:Here's how I understood it: int x,y; // Defined somewhere in the code above for( (x,y) = (0,100); x< y ; (x,y) += (1,-1) ) { ... } So you have variable capture, assignment and add-assign happening.for(int x, y = 0 , 100; x< y ; x, y += 1,-1) { ... } ?Ahem. So are you suggesting that (a,b) means a tuple everywhere but in a for loop, where it is used to separate two statements?If we use the comma operator only for tuples, there needn't to be a special case for loops: for(x, y = 0 , 100; x< y ; x, y += 1,-1) { ... }
Dec 11 2011
On Sun, 11 Dec 2011 06:21:51 -0500, Alex Rønne Petersen <xtzgzorex gmail.com> wrote:On 10-12-2011 02:39, Jonathan M Davis wrote:A lot (all?) of for loop use cases seem to actually work in tuple form. For instance, for(; cond; tuple(++x, y *= 2) ) {} Will behave as expected, although there might be a performance issue.On Friday, December 09, 2011 20:18:36 Robert Jacques wrote:Indeed, having the comma operator in for loops is perfectly normal; even - AlexOn Fri, 09 Dec 2011 01:20:45 -0500, Kagamin<spam here.lot> wrote:I'd _hate_ to be restricted to doing the same operation in the 3rd portion of a for loop for all of its parts. The comma operator is _perfect_ for there, and I wouldn't want to see its behavior changed there regardless. e.g. things like this should continue to be perfectly possible and legal for(; cond; ++x, y *= 2) {} Tuples do _not_ have the proper semantics for a for loop. It would be one thing for the comma operator were to go away in the general case, but it would be horrible IMHO for its behavior to be changed in for loops - be it in an effort to make it act like it's using tuples or any other reason. - Jonathan M DavisOn Thursday, 8 December 2011 at 17:18:57 UTC, Joshua Reusch wrote:Here's how I understood it: int x,y; // Defined somewhere in the code above for( (x,y) = (0,100); x< y ; (x,y) += (1,-1) ) { ... } So you have variable capture, assignment and add-assign happening.for(int x, y = 0 , 100; x< y ; x, y += 1,-1) { ... } ?Ahem. So are you suggesting that (a,b) means a tuple everywhere but in a for loop, where it is used to separate two statements?If we use the comma operator only for tuples, there needn't to be a special case for loops: for(x, y = 0 , 100; x< y ; x, y += 1,-1) { ... }
Dec 11 2011
On Sunday, December 11, 2011 20:19:11 Robert Jacques wrote:A lot (all?) of for loop use cases seem to actually work in tuple form. For instance, for(; cond; tuple(++x, y *= 2) ) {} Will behave as expected, although there might be a performance issue.What if one of the expression's result is void? All in all, I think that it's ludicrous to consider changing the semantics of for loops to use a tuple instead of the comma operator. It's one thing to consider eliminating the comma operator outside of for loops. It's yet another to consider adding built-in templates beyond that, and it's going _way_ too far to change the semantics of the for loop as part of that IMHO. for loops should be left exactly as they are, regardless of what happens with the comma operator outside of for loops. - Jonathan M Davis
Dec 11 2011
On Sun, 11 Dec 2011 20:25:07 -0500, Jonathan M Davis <jmdavisProg gmx.com> wrote:On Sunday, December 11, 2011 20:19:11 Robert Jacques wrote:Ah, thank you. I was observing that my standard for loop syntax actually had the same effective meaning under traditional and tuple semantics, and wasn't seeing the counter example. But, for(; !a.empty && b.empty; a.popFront, b.popFront) {} would never work as a tuple.A lot (all?) of for loop use cases seem to actually work in tuple form. For instance, for(; cond; tuple(++x, y *= 2) ) {} Will behave as expected, although there might be a performance issue.What if one of the expression's result is void? All in all, I think that it's ludicrous to consider changing the semantics of for loops to use a tuple instead of the comma operator. It's one thing to consider eliminating the comma operator outside of for loops. It's yet another to consider adding built-in templates beyond that, and it's going _way_ too far to change the semantics of the for loop as part of that IMHO. for loops should be left exactly as they are, regardless of what happens with the comma operator outside of for loops. - Jonathan M Davis
Dec 11 2011
Alex Rønne Petersen Wrote:I really do not see the value in allowing such syntax in the first place. I've been told that one argument was that generated code might use it, but I have no idea why it would be needed.Aside from the compiler's implementation, one possible use is something I ended up doing in Javascript recently. I have a thing that takes an attribute and pastes it into a code string to check it. given validate="this.value.length > 3" it writes: if(!(this.value.length > 3)) return false; // failed validation since the given string is inside an if statement, you can't put a semicolon in there. So, if you have a check more complex than returning a boolean and want to stuff it all in that string (so functions are out), the comma lets you do it: validate="do something, true" This is pretty ugly style that I think I've only ever done in D inside a for loop... but the point is sometimes something comes up, and it's nice to have another option available, even if it is ugly.
Dec 07 2011
"Adam Ruppe" <destructionator gmail.com> wrote in message news:jbo8rr$rhh$1 digitalmars.com...Alex Rønne Petersen Wrote:Don't know about JS, but D can solve the same problem with anon delegates, which is less obscure anyway.I really do not see the value in allowing such syntax in the first place. I've been told that one argument was that generated code might use it, but I have no idea why it would be needed.Aside from the compiler's implementation, one possible use is something I ended up doing in Javascript recently. I have a thing that takes an attribute and pastes it into a code string to check it. given validate="this.value.length > 3" it writes: if(!(this.value.length > 3)) return false; // failed validation since the given string is inside an if statement, you can't put a semicolon in there. So, if you have a check more complex than returning a boolean and want to stuff it all in that string (so functions are out), the comma lets you do it: validate="do something, true" This is pretty ugly style that I think I've only ever done in D inside a for loop... but the point is sometimes something comes up, and it's nice to have another option available, even if it is ugly.
Dec 07 2011
On 12/07/2011 07:02 PM, Nick Sabalausky wrote:"Adam Ruppe"<destructionator gmail.com> wrote in message news:jbo8rr$rhh$1 digitalmars.com...I think Don said that DMD cannot currently inline any delegates. Imho the spec should even *require* inlining in the special case that such a delegate is immediately executed. (even for debug builds).Alex Rønne Petersen Wrote:Don't know about JS, but D can solve the same problem with anon delegates, which is less obscure anyway.I really do not see the value in allowing such syntax in the first place. I've been told that one argument was that generated code might use it, but I have no idea why it would be needed.Aside from the compiler's implementation, one possible use is something I ended up doing in Javascript recently. I have a thing that takes an attribute and pastes it into a code string to check it. given validate="this.value.length> 3" it writes: if(!(this.value.length> 3)) return false; // failed validation since the given string is inside an if statement, you can't put a semicolon in there. So, if you have a check more complex than returning a boolean and want to stuff it all in that string (so functions are out), the comma lets you do it: validate="do something, true" This is pretty ugly style that I think I've only ever done in D inside a for loop... but the point is sometimes something comes up, and it's nice to have another option available, even if it is ugly.
Dec 07 2011
On Wednesday, December 07, 2011 23:10:53 Timon Gehr wrote:On 12/07/2011 07:02 PM, Nick Sabalausky wrote:lazy doesn't get inlined for the same reason (since it's essentially using a delegate), and that potentially has some nasty implications for performance with regards to stuff like enforce. In the recent thread on std.regex's performance, while enforce was definitely not at the top of the list of functions in the profiler (listed descending by running time), it was definitely a decent portion of the running time of the program. The cost of enforce should be comparable to the cost of assert, but with the issues of inlining lazy and delegates, it definitely isn't that efficient. These sorts of things need to be inlinable. - Jonathan M Davis"Adam Ruppe"<destructionator gmail.com> wrote in message news:jbo8rr$rhh$1 digitalmars.com...I think Don said that DMD cannot currently inline any delegates. Imho the spec should even *require* inlining in the special case that such a delegate is immediately executed. (even for debug builds).Alex Rønne Petersen Wrote:Don't know about JS, but D can solve the same problem with anon delegates, which is less obscure anyway.I really do not see the value in allowing such syntax in the first place. I've been told that one argument was that generated code might use it, but I have no idea why it would be needed.Aside from the compiler's implementation, one possible use is something I ended up doing in Javascript recently. I have a thing that takes an attribute and pastes it into a code string to check it. given validate="this.value.length> 3" it writes: if(!(this.value.length> 3)) return false; // failed validation since the given string is inside an if statement, you can't put a semicolon in there. So, if you have a check more complex than returning a boolean and want to stuff it all in that string (so functions are out), the comma lets you do it: validate="do something, true" This is pretty ugly style that I think I've only ever done in D inside a for loop... but the point is sometimes something comes up, and it's nice to have another option available, even if it is ugly.
Dec 07 2011
On 12/07/2011 08:49 AM, Alex Rønne Petersen wrote:I really do not see the value in allowing such syntax in the first place. I've been told that one argument was that generated code might use it, but I have no idea why it would be needed. Furthermore, this operator makes it very hard to introduce Python-style tuples in the language.IIRC the generated code argument was actually made with regards to the compiler doing internal rewriting of the AST. If I'm remembering correctly, this make it even weaker as, at that point, there is no reason that the form of the AST need match the syntax.
Dec 07 2011
On 08.12.2011 05:52, bcs wrote:On 12/07/2011 08:49 AM, Alex Rønne Petersen wrote:Worth noting that the comma operator inside the compiler is not the same as the one in the language. It supports declarations, in a way that D doesn't. You can't write this in normal D, for example: (int x; , x = 2); But that's what the compiler does internally. The "compiler uses it internally" argument isn't valid at all.I really do not see the value in allowing such syntax in the first place. I've been told that one argument was that generated code might use it, but I have no idea why it would be needed. Furthermore, this operator makes it very hard to introduce Python-style tuples in the language.IIRC the generated code argument was actually made with regards to the compiler doing internal rewriting of the AST. If I'm remembering correctly, this make it even weaker as, at that point, there is no reason that the form of the AST need match the syntax.
Dec 08 2011
Why is this operator still kept around?No offense, but I find it strange/funny that you even ask why! :) Have you never used comma in for loops???
Dec 08 2011
On Thu, 08 Dec 2011 11:17:48 +0200, Dejan Lekic <dejan.lekic gmail.com> wrote:Not sure if it is that relevant for D, but good point. for(auto i=beg(), e=end(); i!=e; ++i) for(auto i, j, k;; ++i, ++k) ...Why is this operator still kept around?No offense, but I find it strange/funny that you even ask why! :) Have you never used comma in for loops???
Dec 08 2011
On Thu, 08 Dec 2011 12:17:20 -0000, so <so so.so> wrote:On Thu, 08 Dec 2011 11:17:48 +0200, Dejan Lekic <dejan.lekic gmail.com> wrote:It's kinda amusing that this thread appeared just as we had a case of this here at work. The developer accidentally coded something like... if (function(..), FALSE) { } Accidentally adding the ", FALSE" /after/ the ) instead of as a new parameter to the function. (note; This was in C++ with default parameter values so the function can in fact take 1-4 args). When I pointed this out, he said "how does that even compile" and was completely unaware of the existence of the comma operator, nor (once I explained it) did he realise it was in any way related to the comma used in for loops. People simply don't think of them as being the same thing at all. Instead, people learn the comma syntax as a special characteristic of the for loop, and use it nowhere else. I think the comma operator is of little benefit (except where used in a for loop) and it is a source of bugs and we'd be better off without it. Even if it means porting C/C++ requires modification, or existing D (I doubt very much of it) breaks. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/Not sure if it is that relevant for D, but good point. for(auto i=beg(), e=end(); i!=e; ++i) for(auto i, j, k;; ++i, ++k) ...Why is this operator still kept around?No offense, but I find it strange/funny that you even ask why! :) Have you never used comma in for loops???
Dec 08 2011
On Thu, 08 Dec 2011 18:02:11 +0200, Regan Heath <regan netmail.co.nz> wrote:When I pointed this out, he said "how does that even compile" and was completely unaware of the existence of the comma operator, nor (once I explained it) did he realise it was in any way related to the comma used in for loops. People simply don't think of them as being the same thing at all. Instead, people learn the comma syntax as a special characteristic of the for loop, and use it nowhere else.Not that related but my all time favorite is still: type a = a + 2; // compiles with no errors, no warnings, no explosions (that i know of)
Dec 08 2011
type a = a + 2; // compiles with no errors, no warnings, no explosions (that i know of)If "type" has the default initialiser, then what is the problem?
Dec 08 2011
On Thu, 08 Dec 2011 19:25:10 +0200, Dejan Lekic <dejan.lekic gmail.com> wrote:What does it do in both C and D context? 1. It does different things. 2. C version even worse because of debug/release difference. 3. If D still does this, it violates the B-D rule (either does the same thing or doesn't compile at all. Actually there are many things violate this rule...) type a; // even this simple code violates B-D rule. What is the use case? . Is there any? . If there is not any you think, but still compiler allows it, it generates nothing but bugs (from experience :) ). Question should be, why does it exist at all?type a = a + 2; // compiles with no errors, no warnings, no explosions (that i know of)If "type" has the default initialiser, then what is the problem?
Dec 08 2011
On Thu, 08 Dec 2011 13:17:44 -0500, so <so so.so> wrote:On Thu, 08 Dec 2011 19:25:10 +0200, Dejan Lekic <dejan.lekic gmail.com> wrote:Actually, these statements don't violate the B-D rule. In C/C++ the value of 'a' prior to use is implementation defined (i.e. it is undefined by the spec) and in practice tends to be some random stack value. D just sets that value to a consistent default, which is completely compliant with the C spec.What does it do in both C and D context? 1. It does different things. 2. C version even worse because of debug/release difference. 3. If D still does this, it violates the B-D rule (either does the same thing or doesn't compile at all. Actually there are many things violate this rule...) type a; // even this simple code violates B-D rule. What is the use case? . Is there any? . If there is not any you think, but still compiler allows it, it generates nothing but bugs (from experience :) ). Question should be, why does it exist at all?type a = a + 2; // compiles with no errors, no warnings, no explosions (that i know of)If "type" has the default initialiser, then what is the problem?
Dec 08 2011
On Fri, 09 Dec 2011 03:19:34 +0200, Robert Jacques <sandford jhu.edu> wrote:On Thu, 08 Dec 2011 13:17:44 -0500, so <so so.so> wrote:I disagree. As you said while in C/C++ same thing gets assigned random values, in D it doesn't. As a result, it changes both the coders' expectations and programs outcome. Even the definitions are different. Undefined there and defined here. I am not sure how to express this. As far as i understand you are saying; Because uninitialized variables are undefined in C, D can act as another C compiler and interpret this rule as it pleases. But in practice no compiler i know does that. And "assuming the variable initialized to some value" is a bad programming practice, which i should say the most popular among its kind. So it clashes with another thing about D, pragmatism.On Thu, 08 Dec 2011 19:25:10 +0200, Dejan Lekic <dejan.lekic gmail.com> wrote:Actually, these statements don't violate the B-D rule. In C/C++ the value of 'a' prior to use is implementation defined (i.e. it is undefined by the spec) and in practice tends to be some random stack value. D just sets that value to a consistent default, which is completely compliant with the C spec.What does it do in both C and D context? 1. It does different things. 2. C version even worse because of debug/release difference. 3. If D still does this, it violates the B-D rule (either does the same thing or doesn't compile at all. Actually there are many things violate this rule...) type a; // even this simple code violates B-D rule. What is the use case? . Is there any? . If there is not any you think, but still compiler allows it, it generates nothing but bugs (from experience :) ). Question should be, why does it exist at all?type a = a + 2; // compiles with no errors, no warnings, no explosions (that i know of)If "type" has the default initialiser, then what is the problem?
Dec 08 2011
On Thu, 08 Dec 2011 21:23:11 -0500, so <so so.so> wrote:On Fri, 09 Dec 2011 03:19:34 +0200, Robert Jacques <sandford jhu.edu> wrote:In a discussion about language specifications, practical implementation details seem tangential to me. Besides, many C++ compilers do set variables to a default bit pattern in debug mode, in order to better detect and account for uninitialized variables. D's major difference is that it also does this in release mode. Besides, strictly speaking, the B-D rule is about valid, portable C/C++ code, which (arguably) isn't anything that uses uninitialized variables. In other words, the B-D rule isn't about D mimicking the behavior of a particular C/C++ compiler, it's about the C spec.On Thu, 08 Dec 2011 13:17:44 -0500, so <so so.so> wrote:I disagree. As you said while in C/C++ same thing gets assigned random values, in D it doesn't. As a result, it changes both the coders' expectations and programs outcome. Even the definitions are different. Undefined there and defined here. I am not sure how to express this. As far as i understand you are saying; Because uninitialized variables are undefined in C, D can act as another C compiler and interpret this rule as it pleases. But in practice no compiler i know does that.On Thu, 08 Dec 2011 19:25:10 +0200, Dejan Lekic <dejan.lekic gmail.com> wrote:Actually, these statements don't violate the B-D rule. In C/C++ the value of 'a' prior to use is implementation defined (i.e. it is undefined by the spec) and in practice tends to be some random stack value. D just sets that value to a consistent default, which is completely compliant with the C spec.What does it do in both C and D context? 1. It does different things. 2. C version even worse because of debug/release difference. 3. If D still does this, it violates the B-D rule (either does the same thing or doesn't compile at all. Actually there are many things violate this rule...) type a; // even this simple code violates B-D rule. What is the use case? . Is there any? . If there is not any you think, but still compiler allows it, it generates nothing but bugs (from experience :) ). Question should be, why does it exist at all?type a = a + 2; // compiles with no errors, no warnings, no explosions (that i know of)If "type" has the default initialiser, then what is the problem?And "assuming the variable initialized to some value" is a bad programming practice, which i should say the most popular among its kind.I totally agree, from a normal control flow perspective. But .init has many uses, particularly in error detection and and repeatability of .init greatly eases debugging.So it clashes with another thing about D, pragmatism.I'm not sure what you mean by that.
Dec 08 2011
On Fri, 09 Dec 2011 06:26:27 +0200, Robert Jacques <sandford jhu.edu> wrote:It was/is one of the defining points of D AFAIK. More than being theoretical it chose to be pragmatic, to solve the problems we face day to day. For the case at hand; Say uninitialized variables in C are undefined but all the compilers do the same thing that makes it in practice defined. So the below line should execute same on all compilers. type a; Same applies to the extensions supported in all major compilers which is absent in language spec. If compilers don't support, they can't sell. To the point. If you want to keep B-D rule with the presence of such big design mistakes (C), you are not being pragmatic at all.So it clashes with another thing about D, pragmatism.I'm not sure what you mean by that.
Dec 08 2011
On Fri, 09 Dec 2011 00:27:39 -0500, so <so so.so> wrote:On Fri, 09 Dec 2011 06:26:27 +0200, Robert Jacques <sandford jhu.edu> wrote:Interesting point. I agree with D being a very pragmatic language (it's one of my favorite things about it), but I come to a different conclusion. The ability to copy and paste code, i.e. source compatible, is one of the most pragmatic things a language can do. And, unlike C++, the B-D rule allows D to break compatibility and therefore convert design mistakes into invalid syntax. However, this is at the cost of preventing the invalidated syntax from being re-used for other means.It was/is one of the defining points of D AFAIK. More than being theoretical it chose to be pragmatic, to solve the problems we face day to day. For the case at hand; Say uninitialized variables in C are undefined but all the compilers do the same thing that makes it in practice defined. So the below line should execute same on all compilers. type a; Same applies to the extensions supported in all major compilers which is absent in language spec. If compilers don't support, they can't sell. To the point. If you want to keep B-D rule with the presence of such big design mistakes (C), you are not being pragmatic at all.So it clashes with another thing about D, pragmatism.I'm not sure what you mean by that.
Dec 09 2011
On 12/08/2011 05:02 PM, Regan Heath wrote:On Thu, 08 Dec 2011 12:17:20 -0000, so <so so.so> wrote:Phobos would break, for example. And some of my code too.On Thu, 08 Dec 2011 11:17:48 +0200, Dejan Lekic <dejan.lekic gmail.com> wrote:It's kinda amusing that this thread appeared just as we had a case of this here at work. The developer accidentally coded something like... if (function(..), FALSE) { } Accidentally adding the ", FALSE" /after/ the ) instead of as a new parameter to the function. (note; This was in C++ with default parameter values so the function can in fact take 1-4 args). When I pointed this out, he said "how does that even compile" and was completely unaware of the existence of the comma operator, nor (once I explained it) did he realise it was in any way related to the comma used in for loops. People simply don't think of them as being the same thing at all. Instead, people learn the comma syntax as a special characteristic of the for loop, and use it nowhere else. I think the comma operator is of little benefit (except where used in a for loop) and it is a source of bugs and we'd be better off without it. Even if it means porting C/C++ requires modification, or existing D (I doubt very much of it) breaks.Not sure if it is that relevant for D, but good point. for(auto i=beg(), e=end(); i!=e; ++i) for(auto i, j, k;; ++i, ++k) ...Why is this operator still kept around?No offense, but I find it strange/funny that you even ask why! :) Have you never used comma in for loops???
Dec 08 2011
On 08.12.2011 20:22, Timon Gehr wrote:On 12/08/2011 05:02 PM, Regan Heath wrote:Are there any cases where you're using comma outside of for loops? I wonder how much would break if were made illegal everywhere else.On Thu, 08 Dec 2011 12:17:20 -0000, so <so so.so> wrote:Phobos would break, for example. And some of my code too.On Thu, 08 Dec 2011 11:17:48 +0200, Dejan Lekic <dejan.lekic gmail.com> wrote:It's kinda amusing that this thread appeared just as we had a case of this here at work. The developer accidentally coded something like... if (function(..), FALSE) { } Accidentally adding the ", FALSE" /after/ the ) instead of as a new parameter to the function. (note; This was in C++ with default parameter values so the function can in fact take 1-4 args). When I pointed this out, he said "how does that even compile" and was completely unaware of the existence of the comma operator, nor (once I explained it) did he realise it was in any way related to the comma used in for loops. People simply don't think of them as being the same thing at all. Instead, people learn the comma syntax as a special characteristic of the for loop, and use it nowhere else. I think the comma operator is of little benefit (except where used in a for loop) and it is a source of bugs and we'd be better off without it. Even if it means porting C/C++ requires modification, or existing D (I doubt very much of it) breaks.Not sure if it is that relevant for D, but good point. for(auto i=beg(), e=end(); i!=e; ++i) for(auto i, j, k;; ++i, ++k) ...Why is this operator still kept around?No offense, but I find it strange/funny that you even ask why! :) Have you never used comma in for loops???
Dec 09 2011
On Friday, December 09, 2011 10:19:18 Don wrote:Are there any cases where you're using comma outside of for loops? I wonder how much would break if were made illegal everywhere else.I'm sure that it would break code, but most people consider it bad practice to use the comma operator for much outside of for loops. Occasionally, it's useful to use one in an expression, but on the whole, it's just confusing and error-prone. And while it might break code to make the comma operator illegal outside of for loops, I would expect that fixing the broken code would generally be rather trivial. The resulting code may not be as compact, but it wouldn't be hard to write. And unless you're dealing with a programmer who uses it uncommonly often, not much code is going to break. - Jonathan M Davis
Dec 09 2011
On 12/09/2011 10:26 AM, Jonathan M Davis wrote:On Friday, December 09, 2011 10:19:18 Don wrote:'most people'?Are there any cases where you're using comma outside of for loops? I wonder how much would break if were made illegal everywhere else.I'm sure that it would break code, but most people consider it bad practice to use the comma operator for much outside of for loops.Occasionally, it's useful to use one in an expression, but on the whole, it's just confusing and error-prone.It is confusing to people who don't know the language. It is a simple construct. In my experience, it is certainly not error prone. If you are aware that such an operator exists.And while it might break code to make the comma operator illegal outside of for loops, I would expect that fixing the broken code would generally be rather trivial.Sure.The resulting code may not be as compact, but it wouldn't be hard to write.It would be a PITA in some cases.And unless you're dealing with a programmer who uses it uncommonly often, not much code is going to break.I _am_ such a programmer.
Dec 09 2011
On Fri, 09 Dec 2011 12:00:57 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:On 12/09/2011 10:26 AM, Jonathan M Davis wrote:Yes, I would guess that you're in the minority here.On Friday, December 09, 2011 10:19:18 Don wrote:'most people'?Are there any cases where you're using comma outside of for loops? I wonder how much would break if were made illegal everywhere else.I'm sure that it would break code, but most people consider it bad practice to use the comma operator for much outside of for loops.It's error prone in cases where you use it without realising, as in the example I posted.Occasionally, it's useful to use one in an expression, but on the whole, it's just confusing and error-prone.It is confusing to people who don't know the language. It is a simple construct. In my experience, it is certainly not error prone. If you are aware that such an operator exists.Really? Give us an example where not having comma makes things significantly difficult.The resulting code may not be as compact, but it wouldn't be hard to write.It would be a PITA in some cases.So it seems :) I don't want to make your life harder but I think this change would make life easier for a large number of people, a small amount of the time. The equation is unbalanced in favour of it's removal, IMO. -- Using Opera's revolutionary email client: http://www.opera.com/mail/And unless you're dealing with a programmer who uses it uncommonly often, not much code is going to break.I _am_ such a programmer.
Dec 09 2011
On 12/09/2011 01:11 PM, Regan Heath wrote:On Fri, 09 Dec 2011 12:00:57 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:'most people' do not care about this discussion, so lets stop it. :o) What I wanted to say is just that throwing in 'most people' does not help an argument, because a) there is no evidence and b) 'most people' are in general just as often (or even more) wrong than 'a few people'.On 12/09/2011 10:26 AM, Jonathan M Davis wrote:Yes, I would guess that you're in the minority here.On Friday, December 09, 2011 10:19:18 Don wrote:'most people'?Are there any cases where you're using comma outside of for loops? I wonder how much would break if were made illegal everywhere else.I'm sure that it would break code, but most people consider it bad practice to use the comma operator for much outside of for loops.That is true for every language construct.It's error prone in cases where you use it without realising, as in the example I posted.Occasionally, it's useful to use one in an expression, but on the whole, it's just confusing and error-prone.It is confusing to people who don't know the language. It is a simple construct. In my experience, it is certainly not error prone. If you are aware that such an operator exists.I already agreed that rewriting the code is trivial. It is just that I usually do not want to spend lots of my time on trivial stuff.Really? Give us an example where not having comma makes things significantly difficult.The resulting code may not be as compact, but it wouldn't be hard to write.It would be a PITA in some cases.If you carefully read my posts you will find that I did never say that I am against removing the comma operator. I would like comma to have tuple semantics. Comma should keep its precedence level and then work like this: if(foo) bar, baz, qux; // the value of the tuple is unused, so no change in semantics if(bar()||(foo(), *++p==(*++x)++)[1]){} // the value is used, so an explicit index is necessary It would make the language more consistent because the comma in expressions would be the same comma as the one that is used elsewhere. That is against the C compatibility rule though, and it would in some cases silently break code.So it seems :)And unless you're dealing with a programmer who uses it uncommonly often, not much code is going to break.I _am_ such a programmer.I don't want to make your life harder but I think this change would make life easier for a large number of people, a small amount of the time. The equation is unbalanced in favour of it's removal, IMO.This part of your post is somewhat contradictory.
Dec 09 2011
On Fri, 09 Dec 2011 13:01:12 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:On 12/09/2011 01:11 PM, Regan Heath wrote:Sure.On Fri, 09 Dec 2011 12:00:57 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:'most people' do not care about this discussion, so lets stop it. :o)On 12/09/2011 10:26 AM, Jonathan M Davis wrote:Yes, I would guess that you're in the minority here.On Friday, December 09, 2011 10:19:18 Don wrote:'most people'?Are there any cases where you're using comma outside of for loops? I wonder how much would break if were made illegal everywhere else.I'm sure that it would break code, but most people consider it bad practice to use the comma operator for much outside of for loops.Excellent.So it seems :)If you carefully read my posts you will find that I did never say that I am against removing the comma operator.How so? R -- Using Opera's revolutionary email client: http://www.opera.com/mail/I don't want to make your life harder but I think this change would make life easier for a large number of people, a small amount of the time. The equation is unbalanced in favour of it's removal, IMO.This part of your post is somewhat contradictory.
Dec 09 2011
On 12/09/2011 02:33 PM, Regan Heath wrote:On Fri, 09 Dec 2011 13:01:12 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:Removing the comma operator makes my life harder. You don't want to do so. You want to remove the comma operator. Conclusion: Today is Monday.On 12/09/2011 01:11 PM, Regan Heath wrote:Sure.On Fri, 09 Dec 2011 12:00:57 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:'most people' do not care about this discussion, so lets stop it. :o)On 12/09/2011 10:26 AM, Jonathan M Davis wrote:Yes, I would guess that you're in the minority here.On Friday, December 09, 2011 10:19:18 Don wrote:'most people'?Are there any cases where you're using comma outside of for loops? I wonder how much would break if were made illegal everywhere else.I'm sure that it would break code, but most people consider it bad practice to use the comma operator for much outside of for loops.Excellent.So it seems :)If you carefully read my posts you will find that I did never say that I am against removing the comma operator.How so? RI don't want to make your life harder but I think this change would make life easier for a large number of people, a small amount of the time. The equation is unbalanced in favour of it's removal, IMO.This part of your post is somewhat contradictory.
Dec 09 2011
On Fri, 09 Dec 2011 13:47:14 -0000, Timon Gehr <timon.gehr gmx.ch> wrote::p 1. I don't want to make your life harder, but (despite that) 2. I do want to remove the comma operator Nothing contradictory there at all, simply cost/benefit. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/Removing the comma operator makes my life harder. You don't want to do so. You want to remove the comma operator. Conclusion: Today is Monday.How so? RI don't want to make your life harder but I think this change would make life easier for a large number of people, a small amount of the time. The equation is unbalanced in favour of it's removal, IMO.This part of your post is somewhat contradictory.
Dec 09 2011
Regan Heath wrote:On Fri, 09 Dec 2011 12:00:57 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:What about just not using comma operator? Yes, I know about keyboard issue. There are many cases when 'typoed' code compiles but doesn't work as programmer would expect. This is not limited to comma op. Some programmers do not like gotos, comma operator or other language constructs. Some like the opposites. I would suggest making a patch to the compiler to introduce a new pragma: pragma(disable, commaOp); and programmers will be able to place it in every source file they want to.On 12/09/2011 10:26 AM, Jonathan M Davis wrote:So it seems :) I don't want to make your life harder but I think this change would make life easier for a large number of people [...]And unless you're dealing with a programmer who uses it uncommonly often, not much code is going to break.I _am_ such a programmer.
Dec 09 2011
On Fri, 09 Dec 2011 13:15:22 -0000, Piotr Szturmaj <bncrbme jadamspam.pl> wrote:Regan Heath wrote:True, but D has already turned a good number of those into errors. This is another example where it could for very little cost, IMO. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/On Fri, 09 Dec 2011 12:00:57 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:What about just not using comma operator? Yes, I know about keyboard issue. There are many cases when 'typoed' code compiles but doesn't work as programmer would expect. This is not limited to comma op.On 12/09/2011 10:26 AM, Jonathan M Davis wrote:So it seems :) I don't want to make your life harder but I think this change would make life easier for a large number of people [...]And unless you're dealing with a programmer who uses it uncommonly often, not much code is going to break.I _am_ such a programmer.
Dec 09 2011
Timon Gehr wrote:It is confusing to people who don't know the language. It is a simple construct. In my experience, it is certainly not error prone. If you are aware that such an operator exists.It may not be error prone to write, but it is error prone to read, because the comma-operator tends to hide in the language noise produced by all those brackets, semicolons, commas, parenthesis and curly braces. I don't like it, if I have to be uber careful when reading trivial code.
Dec 09 2011
On 12/09/2011 02:38 PM, Tobias Pankrath wrote:Timon Gehr wrote:You always have to be careful when reading code. I prefer when there is not a lot to read (dense code).It is confusing to people who don't know the language. It is a simple construct. In my experience, it is certainly not error prone. If you are aware that such an operator exists.It may not be error prone to write, but it is error prone to read, because the comma-operator tends to hide in the language noise produced by all those brackets, semicolons, commas, parenthesis and curly braces. I don't like it, if I have to be uber careful when reading trivial code.
Dec 09 2011
On Friday, December 09, 2011 13:00:57 Timon Gehr wrote:On 12/09/2011 10:26 AM, Jonathan M Davis wrote:In my experience, someone like you who uses the comma operator outside of for loops much at all is incredibly rare. It's far more typical to consider the comma operator confusing and error-prone than it is to use it frequently. - Jonathan M DavisOn Friday, December 09, 2011 10:19:18 Don wrote:'most people'?Are there any cases where you're using comma outside of for loops? I wonder how much would break if were made illegal everywhere else.I'm sure that it would break code, but most people consider it bad practice to use the comma operator for much outside of for loops.Occasionally, it's useful to use one in an expression, but on the whole, it's just confusing and error-prone.It is confusing to people who don't know the language. It is a simple construct. In my experience, it is certainly not error prone. If you are aware that such an operator exists.And while it might break code to make the comma operator illegal outside of for loops, I would expect that fixing the broken code would generally be rather trivial.Sure.The resulting code may not be as compact, but it wouldn't be hard to write.It would be a PITA in some cases.And unless you're dealing with a programmer who uses it uncommonly often, not much code is going to break.I _am_ such a programmer.
Dec 09 2011
On 12/09/2011 10:19 AM, Don wrote:On 08.12.2011 20:22, Timon Gehr wrote:Yes, one for every 65 LOC.On 12/08/2011 05:02 PM, Regan Heath wrote:Are there any cases where you're using comma outside of for loops?On Thu, 08 Dec 2011 12:17:20 -0000, so <so so.so> wrote:Phobos would break, for example. And some of my code too.On Thu, 08 Dec 2011 11:17:48 +0200, Dejan Lekic <dejan.lekic gmail.com> wrote:It's kinda amusing that this thread appeared just as we had a case of this here at work. The developer accidentally coded something like... if (function(..), FALSE) { } Accidentally adding the ", FALSE" /after/ the ) instead of as a new parameter to the function. (note; This was in C++ with default parameter values so the function can in fact take 1-4 args). When I pointed this out, he said "how does that even compile" and was completely unaware of the existence of the comma operator, nor (once I explained it) did he realise it was in any way related to the comma used in for loops. People simply don't think of them as being the same thing at all. Instead, people learn the comma syntax as a special characteristic of the for loop, and use it nowhere else. I think the comma operator is of little benefit (except where used in a for loop) and it is a source of bugs and we'd be better off without it. Even if it means porting C/C++ requires modification, or existing D (I doubt very much of it) breaks.Not sure if it is that relevant for D, but good point. for(auto i=beg(), e=end(); i!=e; ++i) for(auto i, j, k;; ++i, ++k) ...Why is this operator still kept around?No offense, but I find it strange/funny that you even ask why! :) Have you never used comma in for loops???I wonder how much would break if were made illegal everywhere else.These are the occurences of the comma operator in directory 'std': return r2.empty ? (r1 = r, true) : false; return binaryFun!pred(r.front, e) ? (r.popFront(), true) : false; if (f.flPlus) signChar = '+', ++minw; else if (f.flSpace) signChar = ' ', ++minw; if (std.ascii.toLower(p.front) == 'n' && (p.popFront(), std.ascii.toLower(p.front) == 'f') && (p.popFront(), p.empty)) enforce((p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'A') && (p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'N'), new ConvException("error converting input to floating point")); if (indexStart != 0) formatValue(w, indexStart, f), put(w, '$'); if (c == '\"' || c == '\\') put(w, '\\'), put(w, c); else put(w, c); return (++mi.m_cRefs, cast(HXModule)mi); return (++mi.m_cRefs, hModule); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : (assert(false), 6);
Dec 09 2011
On Fri, 09 Dec 2011 11:39:55 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:On 12/09/2011 10:19 AM, Don wrote:All of the above could be improved with the removal of the comma operator, IMO. They are needlessly complicated/confusing with it. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/On 08.12.2011 20:22, Timon Gehr wrote:Yes, one for every 65 LOC.Phobos would break, for example. And some of my code too.Are there any cases where you're using comma outside of for loops?I wonder how much would break if were made illegal everywhere else.These are the occurences of the comma operator in directory 'std': return r2.empty ? (r1 = r, true) : false; return binaryFun!pred(r.front, e) ? (r.popFront(), true) : false; if (f.flPlus) signChar = '+', ++minw; else if (f.flSpace) signChar = ' ', ++minw; if (std.ascii.toLower(p.front) == 'n' && (p.popFront(), std.ascii.toLower(p.front) == 'f') && (p.popFront(), p.empty)) enforce((p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'A') && (p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'N'), new ConvException("error converting input to floating point")); if (indexStart != 0) formatValue(w, indexStart, f), put(w, '$'); if (c == '\"' || c == '\\') put(w, '\\'), put(w, c); else put(w, c); return (++mi.m_cRefs, cast(HXModule)mi); return (++mi.m_cRefs, hModule); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : (assert(false), 6);
Dec 09 2011
Timon Gehr:These are the occurences of the comma operator in directory 'std': return r2.empty ? (r1 = r, true) : false; return binaryFun!pred(r.front, e) ? (r.popFront(), true) : false; if (f.flPlus) signChar = '+', ++minw; else if (f.flSpace) signChar = ' ', ++minw; if (std.ascii.toLower(p.front) == 'n' && (p.popFront(), std.ascii.toLower(p.front) == 'f') && (p.popFront(), p.empty)) enforce((p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'A') && (p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'N'), new ConvException("error converting input to floating point")); if (indexStart != 0) formatValue(w, indexStart, f), put(w, '$'); if (c == '\"' || c == '\\') put(w, '\\'), put(w, c); else put(w, c); return (++mi.m_cRefs, cast(HXModule)mi); return (++mi.m_cRefs, hModule); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : (assert(false), 6);It's ugly code worth fixing/rewriting. If I see something like that in production code, I always burn it with fire and rewrite it. Turning such usages of comma operator into syntax errors looks like a general improvement for D. Bye, bearophile
Dec 09 2011
On Fri, 09 Dec 2011 11:39:55 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:These are the occurences of the comma operator in directory 'std':Here is my /very/ quick re-write of each without looking at the context of each snippet. There may be much better re-writes in context. Re-writing this was problematic /because/ the comma operator makes things that much actually separates enforce parameters! 1)return r2.empty ? (r1 = r, true) : false;if (!r2.empty) return false; r1 = r; return true; 2)return binaryFun!pred(r.front, e) ? (r.popFront(), true) : false;if (!binaryFun!pred(r.front, e)) return false; r.popFront(); return true; 3)if (f.flPlus) signChar = '+', ++minw; else if (f.flSpace) signChar = ' ', ++minw;This is purely {}; avoidance it seems.. if (f.flPlus) { signChar = '+'; ++minw; } else if (f.flSpace) { signChar = ' '; ++minw; } 4)if (std.ascii.toLower(p.front) == 'n' && (p.popFront(), std.ascii.toLower(p.front) == 'f') && (p.popFront(), p.empty))'if' statements with side effects are yuck. I prefer the check for error and bail style but you could use multiple layers of 'if' instead.. if (std.ascii.toLower(p.front) != 'n') //error handling p.popFront(); if (std.ascii.toLower(p.front) != 'f') //error handling p.popFront(); if (!p.empty) //error handling 5)enforce((p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'A') && (p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'N'), new ConvException("error converting input to floating point"));This is blatant enforce abuse IMO.. p.popFront(); if(p.empty || std.ascii.toUpper(p.front) != 'A')) throw new ConvException("error converting input to floating point")); p.popFront(); if(p.empty || std.ascii.toUpper(p.front) != 'N')) throw new ConvException("error converting input to floating point")); 6)if (indexStart != 0) formatValue(w, indexStart, f), put(w, '$');More {}; avoidance.. if (indexStart != 0) { formatValue(w, indexStart, f); put(w, '$'); } 7)if (c == '\"' || c == '\\') put(w, '\\'), put(w, c); else put(w, c);More {}; avoidance.. if (c == '\"' || c == '\\') { put(w, '\\'); put(w, c); } else { put(w, c); } 8)return (++mi.m_cRefs, cast(HXModule)mi);less (), one more ; and <enter>.. ++mi.m_cRefs; return cast(HXModule)mi; 9)return (++mi.m_cRefs, hModule);as above.. ++mi.m_cRefs; return hModule; 10)return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : (assert(false), 6);*Much* clearer with the rewrite.. assert(c <= 0x10FFFF); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : 6; None of the above look significantly harder without the comma operator and quite a few are far clearer (to me) without it. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Dec 09 2011
On 12/09/2011 01:36 PM, Regan Heath wrote:4)Your '//error handling' shortcut hides relevant information.if (std.ascii.toLower(p.front) == 'n' && (p.popFront(), std.ascii.toLower(p.front) == 'f') && (p.popFront(), p.empty))'if' statements with side effects are yuck. I prefer the check for error and bail style but you could use multiple layers of 'if' instead.. if (std.ascii.toLower(p.front) != 'n') //error handling p.popFront(); if (std.ascii.toLower(p.front) != 'f') //error handling p.popFront(); if (!p.empty) //error handling5)This is blatant code duplication.enforce((p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'A') && (p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'N'), new ConvException("error converting input to floating point"));This is blatant enforce abuse IMO.. p.popFront(); if(p.empty || std.ascii.toUpper(p.front) != 'A')) throw new ConvException("error converting input to floating point")); p.popFront(); if(p.empty || std.ascii.toUpper(p.front) != 'N')) throw new ConvException("error converting input to floating point"));7)No comma operator necessary to avoid {}: if(x == '"' || c == '\\') put(w, '\\'); put(w, c);if (c == '\"' || c == '\\') put(w, '\\'), put(w, c); else put(w, c);More {}; avoidance.. if (c == '\"' || c == '\\') { put(w, '\\'); put(w, c); } else { put(w, c); }8)() would not be necessary.return (++mi.m_cRefs, cast(HXModule)mi);less (), one more ; and <enter>.. ++mi.m_cRefs; return cast(HXModule)mi;9)This is a *much* better rewrite: assert(c <= 0x10FFFF); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : 4;return (++mi.m_cRefs, hModule);as above.. ++mi.m_cRefs; return hModule; 10)return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : (assert(false), 6);*Much* clearer with the rewrite.. assert(c <= 0x10FFFF); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : 6;None of the above look significantly harder without the comma operator and quite a few are far clearer (to me) without it.Yah, many of those occurences in Phobos are mostly unnecessary.
Dec 09 2011
On Fri, 09 Dec 2011 13:15:47 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:On 12/09/2011 01:36 PM, Regan Heath wrote:What information? With context I could be more specific about what to do for each/all.4)Your '//error handling' shortcut hides relevant information.if (std.ascii.toLower(p.front) == 'n' && (p.popFront(), std.ascii.toLower(p.front) == 'f') && (p.popFront(), p.empty))'if' statements with side effects are yuck. I prefer the check for error and bail style but you could use multiple layers of 'if' instead.. if (std.ascii.toLower(p.front) != 'n') //error handling p.popFront(); if (std.ascii.toLower(p.front) != 'f') //error handling p.popFront(); if (!p.empty) //error handlingOf the throw line? Sure, and you can re-write with nested 'if' if you prefer. I prefer the code duplication tho.5)This is blatant code duplication.enforce((p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'A') && (p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'N'), new ConvException("error converting input to floating point"));This is blatant enforce abuse IMO.. p.popFront(); if(p.empty || std.ascii.toUpper(p.front) != 'A')) throw new ConvException("error converting input to floating point")); p.popFront(); if(p.empty || std.ascii.toUpper(p.front) != 'N')) throw new ConvException("error converting input to floating point"));Yeah, it was a /quick/ re-write without additional re-factoring (aside from removal of the comma).7)No comma operator necessary to avoid {}: if(x == '"' || c == '\\') put(w, '\\'); put(w, c);if (c == '\"' || c == '\\') put(w, '\\'), put(w, c); else put(w, c);More {}; avoidance.. if (c == '\"' || c == '\\') { put(w, '\\'); put(w, c); } else { put(w, c); }True, but if you're going to use the comma operator, enclosing it in () at makes it more obvious you've done so. I tend to use extra () when using the ?: operator for this reason.8)() would not be necessary.return (++mi.m_cRefs, cast(HXModule)mi);less (), one more ; and <enter>.. ++mi.m_cRefs; return cast(HXModule)mi;Again, I was missing context.. is the return value of 6 not required in release mode?9)This is a *much* better rewrite: assert(c <= 0x10FFFF); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : 4;return (++mi.m_cRefs, hModule);as above.. ++mi.m_cRefs; return hModule; 10)return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : (assert(false), 6);*Much* clearer with the rewrite.. assert(c <= 0x10FFFF); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : 6;:) -- Using Opera's revolutionary email client: http://www.opera.com/mail/None of the above look significantly harder without the comma operator and quite a few are far clearer (to me) without it.Yah, many of those occurences in Phobos are mostly unnecessary.
Dec 09 2011
On 12/09/2011 02:28 PM, Regan Heath wrote:On Fri, 09 Dec 2011 13:15:47 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:You can always grep the Phobos source to get context. Basically, you are suggesting to replace the comma operator with gotos: case 'i': case 'I': p.popFront(); if (std.ascii.toLower(p.front) == 'n' && (p.popFront(), std.ascii.toLower(p.front) == 'f') && (p.popFront(), p.empty)) { // 'inf' return sign ? -Target.infinity : Target.infinity; } goto default; default: {} }On 12/09/2011 01:36 PM, Regan Heath wrote:What information? With context I could be more specific about what to do for each/all.4)Your '//error handling' shortcut hides relevant information.if (std.ascii.toLower(p.front) == 'n' && (p.popFront(), std.ascii.toLower(p.front) == 'f') && (p.popFront(), p.empty))'if' statements with side effects are yuck. I prefer the check for error and bail style but you could use multiple layers of 'if' instead.. if (std.ascii.toLower(p.front) != 'n') //error handling p.popFront(); if (std.ascii.toLower(p.front) != 'f') //error handling p.popFront(); if (!p.empty) //error handlingCode duplication is very error prone. Furthermore I never ever want to duplicate _error handling_ code. That just clutters up the generated machine code if the compiler does not manage to reverse engineer and generate the proper solution.Of the throw line? Sure, and you can re-write with nested 'if' if you prefer. I prefer the code duplication tho.5)This is blatant code duplication.enforce((p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'A') && (p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'N'), new ConvException("error converting input to floating point"));This is blatant enforce abuse IMO.. p.popFront(); if(p.empty || std.ascii.toUpper(p.front) != 'A')) throw new ConvException("error converting input to floating point")); p.popFront(); if(p.empty || std.ascii.toUpper(p.front) != 'N')) throw new ConvException("error converting input to floating point"));You sort of made it look like the comma operator solution was more verbose. ;)Yeah, it was a /quick/ re-write without additional re-factoring (aside from removal of the comma).7)No comma operator necessary to avoid {}: if(x == '"' || c == '\\') put(w, '\\'); put(w, c);if (c == '\"' || c == '\\') put(w, '\\'), put(w, c); else put(w, c);More {}; avoidance.. if (c == '\"' || c == '\\') { put(w, '\\'); put(w, c); } else { put(w, c); }True, but if you're going to use the comma operator, enclosing it in () at makes it more obvious you've done so. I tend to use extra () when using the ?: operator for this reason.8)() would not be necessary.return (++mi.m_cRefs, cast(HXModule)mi);less (), one more ; and <enter>.. ++mi.m_cRefs; return cast(HXModule)mi;I was joking here. Your 'rewrite' of the original example changed its release mode semantics, therefore I did the same thing.Again, I was missing context.. is the return value of 6 not required in release mode?9)This is a *much* better rewrite: assert(c <= 0x10FFFF); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : 4;return (++mi.m_cRefs, hModule);as above.. ++mi.m_cRefs; return hModule; 10)return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : (assert(false), 6);*Much* clearer with the rewrite.. assert(c <= 0x10FFFF); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : 6;:)None of the above look significantly harder without the comma operator and quite a few are far clearer (to me) without it.Yah, many of those occurences in Phobos are mostly unnecessary.
Dec 09 2011
On Fri, 09 Dec 2011 13:42:34 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:On 12/09/2011 02:28 PM, Regan Heath wrote:If using 'goto' is the 'correct' agreed upon style for phobos then, yes. It's not my personal preference however and I'd probably refactor it further if it was my own code.On Fri, 09 Dec 2011 13:15:47 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:You can always grep the Phobos source to get context. Basically, you are suggesting to replace the comma operator with gotos: case 'i': case 'I': p.popFront(); if (std.ascii.toLower(p.front) == 'n' && (p.popFront(), std.ascii.toLower(p.front) == 'f') && (p.popFront(), p.empty)) { // 'inf' return sign ? -Target.infinity : Target.infinity; } goto default; default: {} }On 12/09/2011 01:36 PM, Regan Heath wrote:What information? With context I could be more specific about what to do for each/all.4)Your '//error handling' shortcut hides relevant information.if (std.ascii.toLower(p.front) == 'n' && (p.popFront(), std.ascii.toLower(p.front) == 'f') && (p.popFront(), p.empty))'if' statements with side effects are yuck. I prefer the check for error and bail style but you could use multiple layers of 'if' instead.. if (std.ascii.toLower(p.front) != 'n') //error handling p.popFront(); if (std.ascii.toLower(p.front) != 'f') //error handling p.popFront(); if (!p.empty) //error handlingI can't comment on the machine code aspect. I don't find this particular duplication error prone, but if you do you can use the nested if that I've already mentioned.Code duplication is very error prone. Furthermore I never ever want to duplicate _error handling_ code. That just clutters up the generated machine code if the compiler does not manage to reverse engineer and generate the proper solution.Of the throw line? Sure, and you can re-write with nested 'if' if you prefer. I prefer the code duplication tho.5)This is blatant code duplication.enforce((p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'A') && (p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'N'), new ConvException("error converting input to floating point"));This is blatant enforce abuse IMO.. p.popFront(); if(p.empty || std.ascii.toUpper(p.front) != 'A')) throw new ConvException("error converting input to floating point")); p.popFront(); if(p.empty || std.ascii.toUpper(p.front) != 'N')) throw new ConvException("error converting input to floating point"));My version performs the assert in all cases, throws an assert error in the same/error cases, and still returns the correct/original values. The only change is performing the assert in all cases, so I don't see how that is a problem. Yours however is entirely broken (assuming the return value of 6 is desired/required). R -- Using Opera's revolutionary email client: http://www.opera.com/mail/I was joking here. Your 'rewrite' of the original example changed its release mode semantics, therefore I did the same thing.Again, I was missing context.. is the return value of 6 not required in release mode?10)This is a *much* better rewrite: assert(c <= 0x10FFFF); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : 4;return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : (assert(false), 6);*Much* clearer with the rewrite.. assert(c <= 0x10FFFF); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : 6;
Dec 09 2011
On 12/09/2011 03:25 PM, Regan Heath wrote:On Fri, 09 Dec 2011 13:42:34 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:What you might be missing is that assert(false) is not compiled out in release mode. It emits a 'hlt' instruction which kills your program. However, your assert(c <= 0x10FFFF); will be removed in release mode.On 12/09/2011 02:28 PM, Regan Heath wrote:If using 'goto' is the 'correct' agreed upon style for phobos then, yes. It's not my personal preference however and I'd probably refactor it further if it was my own code.On Fri, 09 Dec 2011 13:15:47 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:You can always grep the Phobos source to get context. Basically, you are suggesting to replace the comma operator with gotos: case 'i': case 'I': p.popFront(); if (std.ascii.toLower(p.front) == 'n' && (p.popFront(), std.ascii.toLower(p.front) == 'f') && (p.popFront(), p.empty)) { // 'inf' return sign ? -Target.infinity : Target.infinity; } goto default; default: {} }On 12/09/2011 01:36 PM, Regan Heath wrote:What information? With context I could be more specific about what to do for each/all.4)Your '//error handling' shortcut hides relevant information.if (std.ascii.toLower(p.front) == 'n' && (p.popFront(), std.ascii.toLower(p.front) == 'f') && (p.popFront(), p.empty))'if' statements with side effects are yuck. I prefer the check for error and bail style but you could use multiple layers of 'if' instead.. if (std.ascii.toLower(p.front) != 'n') //error handling p.popFront(); if (std.ascii.toLower(p.front) != 'f') //error handling p.popFront(); if (!p.empty) //error handlingI can't comment on the machine code aspect. I don't find this particular duplication error prone, but if you do you can use the nested if that I've already mentioned.Code duplication is very error prone. Furthermore I never ever want to duplicate _error handling_ code. That just clutters up the generated machine code if the compiler does not manage to reverse engineer and generate the proper solution.Of the throw line? Sure, and you can re-write with nested 'if' if you prefer. I prefer the code duplication tho.5)This is blatant code duplication.enforce((p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'A') && (p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'N'), new ConvException("error converting input to floating point"));This is blatant enforce abuse IMO.. p.popFront(); if(p.empty || std.ascii.toUpper(p.front) != 'A')) throw new ConvException("error converting input to floating point")); p.popFront(); if(p.empty || std.ascii.toUpper(p.front) != 'N')) throw new ConvException("error converting input to floating point"));My version performs the assert in all cases, throws an assert error in the same/error cases, and still returns the correct/original values. The only change is performing the assert in all cases, so I don't see how that is a problem. Yours however is entirely broken (assuming the return value of 6 is desired/required). RI was joking here. Your 'rewrite' of the original example changed its release mode semantics, therefore I did the same thing.Again, I was missing context.. is the return value of 6 not required in release mode?10)This is a *much* better rewrite: assert(c <= 0x10FFFF); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : 4;return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : (assert(false), 6);*Much* clearer with the rewrite.. assert(c <= 0x10FFFF); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : 6;
Dec 09 2011
On Fri, 09 Dec 2011 14:54:16 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:I was indeed missing that. I couldn't find anything about it on the website. :) R -- Using Opera's revolutionary email client: http://www.opera.com/mail/What you might be missing is that assert(false) is not compiled out in release mode. It emits a 'hlt' instruction which kills your program. However, your assert(c <= 0x10FFFF); will be removed in release mode.My version performs the assert in all cases, throws an assert error in the same/error cases, and still returns the correct/original values. The only change is performing the assert in all cases, so I don't see how that is a problem. Yours however is entirely broken (assuming the return value of 6 is desired/required). RI was joking here. Your 'rewrite' of the original example changed its release mode semantics, therefore I did the same thing.Again, I was missing context.. is the return value of 6 not required in release mode?10)This is a *much* better rewrite: assert(c <= 0x10FFFF); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : 4;return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : (assert(false), 6);*Much* clearer with the rewrite.. assert(c <= 0x10FFFF); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : 6;
Dec 09 2011
On 12/09/2011 04:37 PM, Regan Heath wrote:On Fri, 09 Dec 2011 14:54:16 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:http://d-programming-language.org/expression.html#AssertExpressionI was indeed missing that. I couldn't find anything about it on the website. :) RWhat you might be missing is that assert(false) is not compiled out in release mode. It emits a 'hlt' instruction which kills your program. However, your assert(c <= 0x10FFFF); will be removed in release mode.My version performs the assert in all cases, throws an assert error in the same/error cases, and still returns the correct/original values. The only change is performing the assert in all cases, so I don't see how that is a problem. Yours however is entirely broken (assuming the return value of 6 is desired/required). RI was joking here. Your 'rewrite' of the original example changed its release mode semantics, therefore I did the same thing.Again, I was missing context.. is the return value of 6 not required in release mode?10)This is a *much* better rewrite: assert(c <= 0x10FFFF); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : 4;return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : (assert(false), 6);*Much* clearer with the rewrite.. assert(c <= 0x10FFFF); return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : 6;
Dec 09 2011
On Fri, 09 Dec 2011 15:39:09 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:On 12/09/2011 04:37 PM, Regan Heath wrote:I found that :p .. but nothing about behaviour in release/debug/etc. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/On Fri, 09 Dec 2011 14:54:16 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:http://d-programming-language.org/expression.html#AssertExpressionWhat you might be missing is that assert(false) is not compiled out in release mode. It emits a 'hlt' instruction which kills your program. However, your assert(c <= 0x10FFFF); will be removed in release mode.I was indeed missing that. I couldn't find anything about it on the website. :) R
Dec 12 2011
Regan Heath:It's a known little wart of D2. We discussed about it some time ago. I have asked for a specific and clean way to do it, but D designers have said it's not a big enough wart to deserve an improvement. And as I have predicted, it comes around to bite people in the butt. This is the opposite of perfectionism... Bye, bearophilehttp://d-programming-language.org/expression.html#AssertExpressionI found that :p .. but nothing about behaviour in release/debug/etc.
Dec 12 2011
I didn't notice the other parts of your post before. On 12/09/2011 03:25 PM, Regan Heath wrote:On Fri, 09 Dec 2011 13:42:34 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:The code was probably written that way to give an optimal implementation that does not use goto. How would you refactor the code?On 12/09/2011 02:28 PM, Regan Heath wrote:If using 'goto' is the 'correct' agreed upon style for phobos then, yes. It's not my personal preference however and I'd probably refactor it further if it was my own code.On Fri, 09 Dec 2011 13:15:47 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:You can always grep the Phobos source to get context. Basically, you are suggesting to replace the comma operator with gotos: case 'i': case 'I': p.popFront(); if (std.ascii.toLower(p.front) == 'n' && (p.popFront(), std.ascii.toLower(p.front) == 'f') && (p.popFront(), p.empty)) { // 'inf' return sign ? -Target.infinity : Target.infinity; } goto default; default: {} }On 12/09/2011 01:36 PM, Regan Heath wrote:What information? With context I could be more specific about what to do for each/all.4)Your '//error handling' shortcut hides relevant information.if (std.ascii.toLower(p.front) == 'n' && (p.popFront(), std.ascii.toLower(p.front) == 'f') && (p.popFront(), p.empty))'if' statements with side effects are yuck. I prefer the check for error and bail style but you could use multiple layers of 'if' instead.. if (std.ascii.toLower(p.front) != 'n') //error handling p.popFront(); if (std.ascii.toLower(p.front) != 'f') //error handling p.popFront(); if (!p.empty) //error handlingI don't like the nested if solution. Also it does not work that well in the general case because you might have a || operator somewhere instead of just && operators.I can't comment on the machine code aspect. I don't find this particular duplication error prone, but if you do you can use the nested if that I've already mentioned.Code duplication is very error prone. Furthermore I never ever want to duplicate _error handling_ code. That just clutters up the generated machine code if the compiler does not manage to reverse engineer and generate the proper solution.Of the throw line? Sure, and you can re-write with nested 'if' if you prefer. I prefer the code duplication tho.5)This is blatant code duplication.enforce((p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'A') && (p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'N'), new ConvException("error converting input to floating point"));This is blatant enforce abuse IMO.. p.popFront(); if(p.empty || std.ascii.toUpper(p.front) != 'A')) throw new ConvException("error converting input to floating point")); p.popFront(); if(p.empty || std.ascii.toUpper(p.front) != 'N')) throw new ConvException("error converting input to floating point"));
Dec 09 2011
On Fri, 09 Dec 2011 09:25:34 -0500, Regan Heath <regan netmail.co.nz> wrote:On Fri, 09 Dec 2011 13:42:34 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:goto in this case is acceptable. It's a goto case statement, which technically should be required for fall-through.On 12/09/2011 02:28 PM, Regan Heath wrote:If using 'goto' is the 'correct' agreed upon style for phobos then, yes. It's not my personal preference however and I'd probably refactor it further if it was my own code.On Fri, 09 Dec 2011 13:15:47 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:You can always grep the Phobos source to get context. Basically, you are suggesting to replace the comma operator with gotos: case 'i': case 'I': p.popFront(); if (std.ascii.toLower(p.front) == 'n' && (p.popFront(), std.ascii.toLower(p.front) == 'f') && (p.popFront(), p.empty)) { // 'inf' return sign ? -Target.infinity : Target.infinity; } goto default; default: {} }On 12/09/2011 01:36 PM, Regan Heath wrote:What information? With context I could be more specific about what to do for each/all.4)Your '//error handling' shortcut hides relevant information.if (std.ascii.toLower(p.front) == 'n' && (p.popFront(), std.ascii.toLower(p.front) == 'f') && (p.popFront(), p.empty))'if' statements with side effects are yuck. I prefer the check for error and bail style but you could use multiple layers of 'if' instead.. if (std.ascii.toLower(p.front) != 'n') //error handling p.popFront(); if (std.ascii.toLower(p.front) != 'f') //error handling p.popFront(); if (!p.empty) //error handlingThis case is a perfect example of what is right and wrong with the comma operator. With the comma operator, the single statement avoids code duplication, which is good for maintenance. However, it's extremely hard to see what's going on. Timon, please accept that you may be one of the few who reads that statement and sees perfectly what's happening, I needed to read Regan's version to understand what it does without hurting my head too much. My opinion? I think it's better written like this: p.popFront(); bool bad = void; if(!(bad = p.empty || std.ascii.toUpper(p.front) != 'A')) { p.popFront(); bad = p.empty || std.ascii.toUpper(p.front) != 'N'; } if(bad) throw new ConvException("error converting input to floating point"); And I'd probably reread it again, and throw in some comments to help me remember what the f*** I was doing :) I don't see a smaller solution, or one that doesn't use a temporary, without using the comma operator or duplicating the throw/enforce call. -SteveI can't comment on the machine code aspect. I don't find this particular duplication error prone, but if you do you can use the nested if that I've already mentioned.Code duplication is very error prone. Furthermore I never ever want to duplicate _error handling_ code. That just clutters up the generated machine code if the compiler does not manage to reverse engineer and generate the proper solution.Of the throw line? Sure, and you can re-write with nested 'if' if you prefer. I prefer the code duplication tho.5)This is blatant code duplication.enforce((p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'A') && (p.popFront(), !p.empty && std.ascii.toUpper(p.front) == 'N'), new ConvException("error converting input to floating point"));This is blatant enforce abuse IMO.. p.popFront(); if(p.empty || std.ascii.toUpper(p.front) != 'A')) throw new ConvException("error converting input to floating point")); p.popFront(); if(p.empty || std.ascii.toUpper(p.front) != 'N')) throw new ConvException("error converting input to floating point"));
Dec 09 2011
On Friday, December 09, 2011 12:36:25 Regan Heath wrote:On Fri, 09 Dec 2011 11:39:55 -0000, Timon Gehr <timon.gehr gmx.ch> wrote:Actually, that particular usage of the comma operator makes me almost want to use it that way. It manages to take one of the type of statements that always irritates me when it's multiple lines and make it a single line. - Jonathan M DavisThese are the occurences of the comma operator in directory 'std':Here is my /very/ quick re-write of each without looking at the context of each snippet. There may be much better re-writes in context. Re-writing this was problematic /because/ the comma operator makes things that much actually separates enforce parameters! 1)return r2.empty ? (r1 = r, true) : false;if (!r2.empty) return false; r1 = r; return true;
Dec 09 2011
On Fri, 09 Dec 2011 22:39:55 +1100, Timon Gehr <timon.gehr gmx.ch> wrote:These are the occurences of the comma operator in directory 'std': ...OMG! What ever happened to the idea that source code is meant to AID reading programs and not making it obscured. These are examples for a 'shame' file, or "how not to write useful code". -- Derek Parnell Melbourne, Australia
Dec 09 2011
On 12/09/2011 01:56 PM, Derek wrote:On Fri, 09 Dec 2011 22:39:55 +1100, Timon Gehr <timon.gehr gmx.ch> wrote:You are exaggerating. http://www.ioccc.org/These are the occurences of the comma operator in directory 'std': ...OMG! What ever happened to the idea that source code is meant to AID reading programs and not making it obscured. These are examples for a 'shame' file, or "how not to write useful code".
Dec 09 2011
This is, honestly, ridiculous. On most European keyboard layouts, comma is on the same key as semicolon.Modern shells usually allow to use several keyboard layouts, switching between them as you need. You may want to add US keyboard layout (selected layout is maintained per-window).
Dec 08 2011