digitalmars.D - two suggestions: inner class new itself; error out NaN in debug mode
- z gg.com (22/22) Sep 13 2005 1) inner class cannot new itself:
- Sean Kelly (13/29) Sep 13 2005 I don't understand. Why is a 'this' pointer to B required in order to c...
- z gg.com (9/17) Sep 13 2005 It's non-static inner-class, which contains a hidden 'this' pointer (sho...
- Sean Kelly (5/13) Sep 13 2005 Understood. But shouldn't this only be an issue when access to B's inte...
- James Dunne (10/37) Sep 13 2005 The hardware does trap such cases. It's called a signalling (or noisy)
- Sean Kelly (6/15) Sep 13 2005 SIGFPE is a standard C signal so it should work on Windows as well. Now...
- Don Clugston (12/34) Sep 14 2005 Even quiet NANs will trigger an exception when they are used in <,==,<
- =?UTF-8?B?VGhvbWFzIEvDvGhuZQ==?= (11/11) Sep 13 2005 idea:
- Derek Parnell (9/23) Sep 13 2005 I haven't got any idea about what you are trying to do. It is not obviou...
- Jarrett Billingsley (11/14) Sep 13 2005 This:
- Derek Parnell (16/35) Sep 13 2005 Okay, so the general form would be ...
- Thomas Kühne (4/34) Sep 14 2005 Yes.
- Derek Parnell (7/48) Sep 14 2005 I was not making *any* judgment on the idea. I was only trying to gain
- Manfred Nowak (7/9) Sep 14 2005 [...]
- Derek Parnell (10/20) Sep 14 2005 What the hell does that mean?
- Manfred Nowak (10/17) Sep 14 2005 [...]
- Derek Parnell (39/59) Sep 14 2005 Okay I get the confusion now. When I said "Typeof(Expression)" I did not
- Manfred Nowak (5/7) Sep 15 2005 [...]
- Stewart Gordon (12/24) Sep 14 2005 You can do
- Georg Wrede (26/33) Sep 15 2005 To Stewart: Cool!
- Manfred Nowak (6/8) Sep 15 2005 [...]
1) inner class cannot new itself: class A { B newB() {return new B();} class B { B dup() { B r; r = newB(); // workaround r = new B(); // error out: inner.d(7): no 'this' for nested class B return r; } } } I understand the reason, and I know the workaround; but can we make it legal, by just copying the 'this' pointer (should be called 'outer' really) from the invoking object? So writing innerClass.dup will be much easier. 2) generate runtime error-out in debug mode when a float value NaN is evaluated. The propagation property of NaN as init value of float is great: whenever NaN is used as an operand, the result is NaN. The only problem is the programmer still need to trace back the computation path to determine the locate of the bug. I wonder if the compiler can help on this: in debug mode, whenever a NaN is evaluated, generate a runtime error straight away. So the programmer can immediate identify the bug location.
Sep 13 2005
In article <dg74l5$1q57$1 digitaldaemon.com>, z gg.com says...1) inner class cannot new itself: class A { B newB() {return new B();} class B { B dup() { B r; r = newB(); // workaround r = new B(); // error out: inner.d(7): no 'this' for nested class B return r; } } } I understand the reason, and I know the workaround; but can we make it legal, by just copying the 'this' pointer (should be called 'outer' really) from the invoking object? So writing innerClass.dup will be much easier.I don't understand. Why is a 'this' pointer to B required in order to construct a new instance of B? Or perhaps you left a 'this' out of the example? In this case, that the code doesn't work seems entirely reasonable.2) generate runtime error-out in debug mode when a float value NaN is evaluated.Interesting idea. Is there any way to accomplish this in hardware? It would stink having the compiler insert evaluations after every floating-point operation. Sean
Sep 13 2005
It's non-static inner-class, which contains a hidden 'this' pointer (should be called 'outer' really) to the enclosing object. Right now D's nested class have the same semantics as in Java, check "What's New for D 0.126", and also http://digitalmars.com/d/class.html#nestedI understand the reason, and I know the workaround; but can we make it legal, by just copying the 'this' pointer (should be called 'outer' really) from the invoking object? So writing innerClass.dup will be much easier.I don't understand. Why is a 'this' pointer to B required in order to construct a new instance of B?Interesting idea. Is there any way to accomplish this in hardware? It would stink having the compiler insert evaluations after every floating-point operation.It would be great if this can be caught by setting up some hardware traps. Even if this cannot be done by hardware, I think it will still help the programmer a lot by software simulation. Maybe another flag (e.g. "-NaN") can be introduced to let the programmer explicitly enable this behaviour. It may runs slow, but you will identify the bug straight away.
Sep 13 2005
In article <dg7d1c$23mi$1 digitaldaemon.com>, z gg.com says...Understood. But shouldn't this only be an issue when access to B's internal data is necessary? Constructing a new instance of B is more akin to calling a function than to accessing data. SeanIt's non-static inner-class, which contains a hidden 'this' pointer (should be called 'outer' really) to the enclosing object.I understand the reason, and I know the workaround; but can we make it legal, by just copying the 'this' pointer (should be called 'outer' really) from the invoking object? So writing innerClass.dup will be much easier.I don't understand. Why is a 'this' pointer to B required in order to construct a new instance of B?
Sep 13 2005
z gg.com wrote:The hardware does trap such cases. It's called a signalling (or noisy) NaN. Most NaNs, however, are quiet NaNs. D's float.nan is a quiet NaN, which does not signal when evaluated. I'm not an expert on the IEEE floating point spec by any means. I'm also not quite sure how the signal from the FPU gets to the CPU to the application... I believe on Linux it is achieved with a SIGFPE signal sent to the app, which must trap it and handle it accordingly. I'm not sure how easy or difficult it would be to achieve the same effect using exceptions.It's non-static inner-class, which contains a hidden 'this' pointer (should be called 'outer' really) to the enclosing object. Right now D's nested class have the same semantics as in Java, check "What's New for D 0.126", and also http://digitalmars.com/d/class.html#nestedI understand the reason, and I know the workaround; but can we make it legal, by just copying the 'this' pointer (should be called 'outer' really) from the invoking object? So writing innerClass.dup will be much easier.I don't understand. Why is a 'this' pointer to B required in order to construct a new instance of B?Interesting idea. Is there any way to accomplish this in hardware? It would stink having the compiler insert evaluations after every floating-point operation.It would be great if this can be caught by setting up some hardware traps. Even if this cannot be done by hardware, I think it will still help the programmer a lot by software simulation. Maybe another flag (e.g. "-NaN") can be introduced to let the programmer explicitly enable this behaviour. It may runs slow, but you will identify the bug straight away.
Sep 13 2005
In article <dg80p3$2m8s$1 digitaldaemon.com>, James Dunne says...The hardware does trap such cases. It's called a signalling (or noisy) NaN. Most NaNs, however, are quiet NaNs. D's float.nan is a quiet NaN, which does not signal when evaluated. I'm not an expert on the IEEE floating point spec by any means. I'm also not quite sure how the signal from the FPU gets to the CPU to the application... I believe on Linux it is achieved with a SIGFPE signal sent to the app, which must trap it and handle it accordingly. I'm not sure how easy or difficult it would be to achieve the same effect using exceptions.SIGFPE is a standard C signal so it should work on Windows as well. Now that I think about it, std.c.fenv has functions to specify floating-point behavior, though I've never actually used them. There's a copy of a D header here: http://svn.dsource.org/projects/ares/trunk/src/ares/std/c/fenv.d Sean
Sep 13 2005
Sean Kelly wrote:In article <dg80p3$2m8s$1 digitaldaemon.com>, James Dunne says...Even quiet NANs will trigger an exception when they are used in <,==,< comparisons, and they also trigger exceptions if they arise during a calculation. If D were to provide an option to make uninitialized variables be SNANs, you'd have immediate, 100% detection, but even with QNANs you'll catch them easily. Would work just as well in release mode as in debug mode. Heck, in debug mode you could use the bits inside the SNAN to be an index into a table of all variables in the program, so the error message could be: floating point variable classY.func2().somevar was used before being initialised.The hardware does trap such cases. It's called a signalling (or noisy) NaN. Most NaNs, however, are quiet NaNs. D's float.nan is a quiet NaN, which does not signal when evaluated. I'm not an expert on the IEEE floating point spec by any means. I'm also not quite sure how the signal from the FPU gets to the CPU to the application... I believe on Linux it is achieved with a SIGFPE signal sent to the app, which must trap it and handle it accordingly. I'm not sure how easy or difficult it would be to achieve the same effect using exceptions.SIGFPE is a standard C signal so it should work on Windows as well. Now that I think about it, std.c.fenv has functions to specify floating-point behavior, though I've never actually used them. There's a copy of a D header here: http://svn.dsource.org/projects/ares/trunk/src/ares/std/c/fenv.d Sean
Sep 14 2005
idea: "() ? (A) : (B) = rvalue;" is legal, if A and B are legal lvalues. sample code: int a = 3; int b = 7; ((a > b) ? (a) : (b)) = a*b + (b << 1) - (a >> 1) * (a & b); reason: Limit code duplication and use of temporary variables in order to reduce the bug-proneness of complex evaluations. As far as I am aware there are no side effects for existing code.
Sep 13 2005
On Wed, 14 Sep 2005 01:07:00 +0200, Thomas Kühne wrote:idea: "() ? (A) : (B) = rvalue;" is legal, if A and B are legal lvalues. sample code: int a = 3; int b = 7; ((a > b) ? (a) : (b)) = a*b + (b << 1) - (a >> 1) * (a & b); reason: Limit code duplication and use of temporary variables in order to reduce the bug-proneness of complex evaluations. As far as I am aware there are no side effects for existing code.I haven't got any idea about what you are trying to do. It is not obvious to me at all. Can you rewrite your example using the long method so I can see the logic flow etc.... -- Derek (skype: derek.j.parnell) Melbourne, Australia 14/09/2005 10:03:04 AM
Sep 13 2005
"Derek Parnell" <derek psych.ward> wrote in message news:12zsfnc0t7lua.1wbg7upo8ws6s$.dlg 40tude.net...I haven't got any idea about what you are trying to do. It is not obvious to me at all. Can you rewrite your example using the long method so I can see the logic flow etc....This: (a < b) ? (a) : (b) = 15; Would be the same as: if(a < b) a = 15; else b = 15; So it's using the ?: to select the destination of the assignment instead of the source.
Sep 13 2005
On Tue, 13 Sep 2005 20:08:02 -0400, Jarrett Billingsley wrote:"Derek Parnell" <derek psych.ward> wrote in message news:12zsfnc0t7lua.1wbg7upo8ws6s$.dlg 40tude.net...Okay, so the general form would be ... (BooleanExpression) ? (Identifier1) : (Identifier2) = Expression; which would be equivalent to ... { // Start a scoping block. Typeof(Expression) Temp = Expression; if (BooleanExpression == true) Identifier1 = Temp; else Identifier2 = Temp; } -- Derek (skype: derek.j.parnell) Melbourne, Australia 14/09/2005 10:11:09 AMI haven't got any idea about what you are trying to do. It is not obvious to me at all. Can you rewrite your example using the long method so I can see the logic flow etc....This: (a < b) ? (a) : (b) = 15; Would be the same as: if(a < b) a = 15; else b = 15; So it's using the ?: to select the destination of the assignment instead of the source.
Sep 13 2005
In article <1otsutm9b7edw$.p5znknydurvg.dlg 40tude.net>, Derek Parnell says...On Tue, 13 Sep 2005 20:08:02 -0400, Jarrett Billingsley wrote:Yes. Now consider to write 5 successive scopes and compare it with the ?: notation. Thomas"Derek Parnell" <derek psych.ward> wrote in message news:12zsfnc0t7lua.1wbg7upo8ws6s$.dlg 40tude.net...Okay, so the general form would be ... (BooleanExpression) ? (Identifier1) : (Identifier2) = Expression; which would be equivalent to ... { // Start a scoping block. Typeof(Expression) Temp = Expression; if (BooleanExpression == true) Identifier1 = Temp; else Identifier2 = Temp; }I haven't got any idea about what you are trying to do. It is not obvious to me at all. Can you rewrite your example using the long method so I can see the logic flow etc....This: (a < b) ? (a) : (b) = 15; Would be the same as: if(a < b) a = 15; else b = 15; So it's using the ?: to select the destination of the assignment instead of the source.
Sep 14 2005
On Wed, 14 Sep 2005 14:29:57 +0000 (UTC), Thomas Kühne wrote:In article <1otsutm9b7edw$.p5znknydurvg.dlg 40tude.net>, Derek Parnell says...I was not making *any* judgment on the idea. I was only trying to gain understanding. -- Derek Parnell Melbourne, Australia 15/09/2005 2:02:47 AMOn Tue, 13 Sep 2005 20:08:02 -0400, Jarrett Billingsley wrote:Yes. Now consider to write 5 successive scopes and compare it with the ?: notation."Derek Parnell" <derek psych.ward> wrote in message news:12zsfnc0t7lua.1wbg7upo8ws6s$.dlg 40tude.net...Okay, so the general form would be ... (BooleanExpression) ? (Identifier1) : (Identifier2) = Expression; which would be equivalent to ... { // Start a scoping block. Typeof(Expression) Temp = Expression; if (BooleanExpression == true) Identifier1 = Temp; else Identifier2 = Temp; }I haven't got any idea about what you are trying to do. It is not obvious to me at all. Can you rewrite your example using the long method so I can see the logic flow etc....This: (a < b) ? (a) : (b) = 15; Would be the same as: if(a < b) a = 15; else b = 15; So it's using the ?: to select the destination of the assignment instead of the source.
Sep 14 2005
Derek Parnell wrote: [...]Okay, so the general form would be ...[...]Typeof(Expression) Temp = Expression;[...] No. Because, D has at least that discontinuity with overloaded functions. -manfred
Sep 14 2005
On Wed, 14 Sep 2005 14:57:14 +0000 (UTC), Manfred Nowak wrote:Derek Parnell wrote: [...]What the hell does that mean? I did say "equivalent" right? All I meant was that it would AS IF one created a temporary variable that had the same type as the expression and assigned the expression to that temporary. What has that got to do with overloaded functions? -- Derek Parnell Melbourne, Australia 15/09/2005 2:04:43 AMOkay, so the general form would be ...[...]Typeof(Expression) Temp = Expression;[...] No. Because, D has at least that discontinuity with overloaded functions.
Sep 14 2005
Derek Parnell wrote: [...][...]Okay, so the general form would be ...[...]Typeof(Expression) Temp = Expression;I did say "equivalent" right? All I meant was that it would AS IF one created a temporary variable that had the same type as the expression and assigned the expression to that temporary.Then I do not understand what you might mean with "as if".What has that got to do with overloaded functions?If the RHS is the adress of an overloaded function `&f' then currently `typeof( &f)' has the type of the first definition of `f', which might be neither the type of the `?'-branch nor the type of the `:'-branch of the `?:'-operator. Therefore the general form is to take `typeof( LHS)' instead of `typeof( RHS)'. -manfred
Sep 14 2005
On Thu, 15 Sep 2005 05:32:29 +0000 (UTC), Manfred Nowak wrote:Derek Parnell wrote: [...]Okay I get the confusion now. When I said "Typeof(Expression)" I did not actually mean that we would use the D typeof() function. It was just my attempt at using shorthand to say 'whatever the type of the Expression is, we would use the exact same type for the temporary variable'. Here it is in code, which should remove some confusion... <code> real foo(char a, short b) { return 10.0L; } real foo(int a, long b) { return 20.0L; } void main() { typedef real function(int, long) r_foo_i_l; r_foo_i_l d; r_foo_i_l e; int a = 1; int b = 3; // Implementing ((a<b) ? (d) : (e) = &foo); { r_foo_i_l temp = &foo; if (a<b) d = temp; else e = temp; } assert( d !is null ); assert( d(1, 2L) == 20.0L ); } </code> -- Derek (skype: derek.j.parnell) Melbourne, Australia 15/09/2005 3:39:40 PM[...]Okay, so the general form would be ...[...]Typeof(Expression) Temp = Expression;I did say "equivalent" right? All I meant was that it would AS IF one created a temporary variable that had the same type as the expression and assigned the expression to that temporary.Then I do not understand what you might mean with "as if".What has that got to do with overloaded functions?If the RHS is the adress of an overloaded function `&f' then currently `typeof( &f)' has the type of the first definition of `f', which might be neither the type of the `?'-branch nor the type of the `:'-branch of the `?:'-operator. Therefore the general form is to take `typeof( LHS)' instead of `typeof( RHS)'.
Sep 14 2005
Derek Parnell wrote: [...]When I said "Typeof(Expression)" I did not actually mean that we would use the D typeof() function.[...] I understand now. Thank you. -manfred
Sep 15 2005
Thomas Kühne wrote:idea: "() ? (A) : (B) = rvalue;" is legal, if A and B are legal lvalues. sample code: int a = 3; int b = 7; ((a > b) ? (a) : (b)) = a*b + (b << 1) - (a >> 1) * (a & b); reason: Limit code duplication and use of temporary variables in order to reduce the bug-proneness of complex evaluations.You can do *((a > b) ? (&a) : (&b)) = a*b + (b << 1) - (a >> 1) * (a & b); Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- C++ a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Sep 14 2005
To Stewart: Cool! To OP: This is all very nice. But honestly, I don't see how this could possibly alleviate "bug-proneness". Number one rule of avoiding bugs is: write clear code. Number two is: Keep It Simple, Stupid. Number three: But not any simpler than that. Considering all this, I can't recommend the above style to anybody. Ideally, code should be written so that what it does is immediately visible, at first sight. One should also remember that many local temporary variables never get compiled into code. They are there only to make the programmer's intentions explicit -- and the compiler knows that. At the same time, the compiled code may contain temporary variables not invented by the programmer (mostly in registers and the stack). For example, in the above code, the variable "a" is evaluated several times: chances are the compiled code only evaluates it once, and uses this (locally temporarily stored) value instead. It is usual to find "optimisations" in program code, especially written by folks in "the C mindset". In the old times, when the compilers were simpler, the written code pretty much got compiled "as is". And that was okay, since C was essentially a "machine independent high level assembly language". Today we are going away from that -- even with C compilers. (Which means "what you write is what you get" is becoming history.) Code clarity and simplicity are much more valuable than stealing a few clock cycles or bytes, and smart compilers do that better than the programmer anyway.reason: Limit code duplication and use of temporary variables in order to reduce the bug-proneness of complex evaluations.You can do *((a > b) ? (&a) : (&b)) = a*b + (b << 1) - (a >> 1) * (a & b);
Sep 15 2005
Georg Wrede wrote: [...]Considering all this, I can't recommend the above style to anybody.[...] I agree with you and the arguments you are giving. But then: how to justify the existence of the asm-statement? -manfred
Sep 15 2005