digitalmars.D.announce - NaNs Just Don't Get No Respect
- Walter Bright (4/4) Aug 17 2012 Our discussion on this in the last few days inspired me to write a blog ...
- bearophile (10/11) Aug 17 2012 You have omitted the detail that double.nan !is double.init.
- F i L (4/10) Aug 17 2012 Why would it matter what is "normal"? Normality is constantly
- bearophile (11/12) Aug 17 2012 It matters to me because I am curious.
- Walter Bright (2/4) Aug 17 2012 I have no idea. Please ask them and report back.
- Bernard Helyer (16/21) Aug 18 2012 "When a non-programmer hears about Michael’s articles the
- Peter Alexander (34/41) Aug 18 2012 I'd also like to know this.
- Walter Bright (10/18) Aug 18 2012 I find this peculiar, as the open source software movement is frequently...
- Leandro Lucarella (16/24) Aug 20 2012 Well, free software[1] is closer to communism (or socialism), open
- Don Clugston (7/18) Aug 20 2012 They write journal articles instead. Producing journal articles have
- F i L (77/79) Aug 17 2012 Your example:
- Jesse Phillips (5/14) Aug 17 2012 It is not flawed as that is exactly what he said condition1 did
- F i L (54/70) Aug 18 2012 It's flawed because condition2 relies upon condition1 to function
- bearophile (8/9) Aug 18 2012 Some people suggest:
- Jesse Phillips (16/25) Aug 18 2012 This greatly changes the semantics of the code. I do not disagree
- F i L (14/37) Aug 18 2012 I agree, and that's my point here. The original example is an
- Jesse Phillips (8/11) Aug 18 2012 It is this statement that indicates you didn't fully comprehend
- Nick Sabalausky (5/18) Aug 18 2012 Bullshit, I've used C# which does exactly what Walter is arguing
- Walter Bright (2/5) Aug 18 2012 I've seen this problem in the real world, even though you don't make suc...
- Nick Sabalausky (16/24) Aug 18 2012 I've seen lots of stupid shit in production code. I've seen a
- Walter Bright (4/8) Aug 18 2012 I'm less willing to throw default initialization out - I like it & rely ...
- Michel Fortin (21/30) Aug 19 2012 I like default initialization too, and I rely on it. By that I mean
- Peter Alexander (25/55) Aug 19 2012 The problem with implicit initialisation to zero is that it is
- Walter Bright (8/16) Aug 19 2012 NaNs in your output are pretty obvious. For example, if your accounting ...
- Minas Mina (2/2) Aug 19 2012 I was against nan being the dafault value, but now I that I think
- Peter Alexander (7/17) Aug 20 2012 The problem is that it's easy for even NaN's to be filtered out.
- cal (9/28) Aug 20 2012 I just tried this:
- Peter Alexander (7/15) Aug 20 2012 It's tricky. The only way (that I'm aware of) to get it to return
- bearophile (11/17) Aug 20 2012 Few possibilities:
- Don Clugston (7/37) Aug 21 2012 No, it's the other way around.
- cal (4/11) Aug 21 2012 I did not know that. It seems like a not-so-useful rule but I
- renoX (21/26) Aug 21 2012 In theory, one could prevent this by setting the floating point
- Nick Sabalausky (19/36) Aug 18 2012 If that's the case, then the code is far too damn fragile in the first
- Davidson Corry (28/45) Aug 18 2012 With respect, I think that you are conflating two different questions.
- Adam D. Ruppe (8/10) Aug 18 2012 enum BOOL {
- Walter Bright (7/12) Aug 18 2012 I used to work with digital electronics. There, "boolean" logic actually...
- Nick Sabalausky (11/26) Aug 18 2012 Heh, that's probably the #1 classic Daily WTF :)
- Walter Bright (2/4) Aug 18 2012 Yup, it turns out that all 4 states are very useful.
- Simen Kjaeraas (14/26) Aug 19 2012 Like someone on Reddit mentioned, VHDL has 9 boolean states:
- Nick Sabalausky (59/115) Aug 18 2012 No offense taken (or intended), but I think you're conflating the
- Davidson Corry (42/104) Aug 20 2012 I'm glad. And it's entirely likely that I missed something. I didn't
- Adam D. Ruppe (4/4) Aug 17 2012 I remember you (Walter) or somebody else talking about signaling
- Walter Bright (2/6) Aug 17 2012 http://news.ycombinator.com/item?id=4399635
- bearophile (5/5) Aug 18 2012 Another sub-thread that shows a very important thing, that's
- Walter Bright (6/8) Aug 18 2012 Oh come on. That's called a "user defined type."
- bearophile (14/15) Aug 19 2012 This D code compiles and it throws an "Enforcement failed"
- Walter Bright (2/5) Aug 19 2012 That's called disabling the default constructor with @disable.
- Simen Kjaeraas (11/18) Aug 19 2012 Nope. What bearophile is talking about is something more akin to this,
- Walter Bright (4/9) Aug 19 2012 You'd want the int to be the non-nullable type. You can do this with D's...
- Simen Kjaeraas (12/25) Aug 19 2012 We could define a Nullable!T that does not allow access to the payload
- Andrei Alexandrescu (3/6) Aug 18 2012 Homerun. Nice!!
- Jonathan M Davis (6/13) Aug 18 2012 FWIW, I'm very surprised by how negatively many programmers seem to reac...
- Nick Sabalausky (6/9) Aug 18 2012 Yea, it's kind of like Unicode: ASCII is much simpler and therefore far
- dennis luehring (3/13) Aug 18 2012 i think many of these programmers seems to think that D is introducing
- Sean Cavanaugh (4/21) Aug 18 2012 Nobody knows how floats work, without being locked in a closet for a at
- Walter Bright (4/7) Aug 19 2012 I was forced to figure out how they work in excruciating detail, as I ha...
- Nick Sabalausky (4/10) Aug 19 2012 Sorry, I don't understand, where are you saying 99% of precision
- Sean Cavanaugh (16/26) Aug 20 2012 Chaining algorithms together without regard to how the floats are
- Peter Alexander (2/18) Aug 19 2012 Yes, I got this impression as well. What a sad state of affairs.
- Walter Bright (2/3) Aug 19 2012 Yup. NaNs just don't get no respect, I tell ya! No respect at all!
- Mike James (4/5) Aug 19 2012 Yup. NaNs just don't get no respect, I tell ya! No respect at all!
- Chad J (37/41) Aug 19 2012 Walter, I know you like to make the easy thing the right thing. I like
- Walter Bright (15/47) Aug 19 2012 I'm sorry, it's not debugging hell. I've done an awful lot of "figure ou...
- Chad J (40/100) Aug 19 2012 Most of the programs I've worked on, be it hobby games or business apps
- Walter Bright (3/4) Aug 19 2012 Set the control word for the x87 to turn it on. Probably have to do a li...
- Andrej Mitrovic (2/7) Aug 20 2012 I thought you could do by setting FloatingPointControl in std.math.
- Chad J (4/14) Aug 21 2012 That looks much more convenient and clean.
- renoX (4/22) Aug 21 2012 Except that it doesn't seem to work as expected (maybe an old
- Don Clugston (3/23) Aug 21 2012 Yeah, there's a bug in the code generation, at the moment for 80-bit
- FeepingCreature (1/1) Aug 19 2012 See Subject :)
- Caligo (6/11) Aug 20 2012 Any chance that math.isNaN() will work at compile-time in the future?
Our discussion on this in the last few days inspired me to write a blog post about it: http://www.reddit.com/r/programming/comments/yehz4/nans_just_dont_get_no_respect/ http://www.drdobbs.com/cpp/nans-just-dont-get-no-respect/240005723
Aug 17 2012
Walter Bright:http://www.drdobbs.com/cpp/nans-just-dont-get-no-respect/240005723You have omitted the detail that double.nan !is double.init. On a more general note, I know many professionals in other fields that never write small articles about what they are doing. So is it normal just for programmers to write (small) articles like this? I write them, and other programmers I know write similar things. Maybe to program you need (among other things) active linguistic centers in the brain :-) Bye, bearophile
Aug 17 2012
bearophile wrote:On a more general note, I know many professionals in other fields that never write small articles about what they are doing. So is it normal just for programmers to write (small) articles like this? I write them, and other programmers I know write similar things. Maybe to program you need (among other things) active linguistic centers in the brain :-)Why would it matter what is "normal"? Normality is constantly changing anyways. Or are you just curios if it's been common practice in the past?
Aug 17 2012
F i L:Why would it matter what is "normal"?It matters to me because I am curious. Why aren't my friends that work or study chemistry writing free small online articles like my programmer&CS friends do? Maybe it's systematic differences in their brain brain? Or it's just more easy to talk about coding compared to botany and chemistry and making engines? Or maybe programmers don't know what they are doing? Or maybe it's just I am not looking in the right places? :-) Bye, bearophile
Aug 17 2012
On 8/17/2012 8:03 PM, bearophile wrote:Why aren't my friends that work or study chemistry writing free small online articles like my programmer&CS friends do?I have no idea. Please ask them and report back.
Aug 17 2012
On Saturday, 18 August 2012 at 05:07:19 UTC, Walter Bright wrote:On 8/17/2012 8:03 PM, bearophile wrote:"When a non-programmer hears about Michael’s articles the source code I have released, I usually get a stunned “WTF would you do that for???” look. They don’t get it. Programming is not a zero-sum game. Teaching something to a fellow pro- grammer doesn’t take it away from you. I’m happy to share I can, because I’m in it for thelove of programming. The Ferraris are just gravy, honest!" -John Carmack --- I enjoyed ze article very much.Why aren't my friends that work or study chemistry writing free small online articles like my programmer&CS friends do?I have no idea. Please ask them and report back.
Aug 18 2012
On Saturday, 18 August 2012 at 03:03:23 UTC, bearophile wrote:Why aren't my friends that work or study chemistry writing free small online articles like my programmer&CS friends do? Maybe it's systematic differences in their brain brain? Or it's just more easy to talk about coding compared to botany and chemistry and making engines? Or maybe programmers don't know what they are doing? Or maybe it's just I am not looking in the right places? :-)I'd also like to know this. Maybe it's just the size of the audience. There's a very large community of programmers online, but the community of chemists and botanists is not so large, so there's less reason to share online. Maybe it's because programming is so accessible, allowing younger, more opinionated people to share their thoughts. It's easy to achieve something in programming: just download a compiler/interpreter, follow some online tutorials and you'll have something worth sharing. In Chemistry on the other hand, you really need to go to university before you can start doing something beyond simple experiments with household ingredients. Maybe it's a delusion of grandeur. A lot of programmers have the idea that they could program up the next big computer game, or make the next Facebook or Twitter. When they inevitably fail, they turn to blogging ("Those who can't, teach"). I've noticed this especially on HackerNews, which is of course filled with people with such delusions. P.S. before anyone gets offended, I'm not suggesting this applies to all programming bloggers! Maybe it's related to the tendency for programmers to be libertarians, which would also explain the whole open source software movement. They want to share knowledge freely, and online articles would be part of that. Maybe it's related to the religion thing. Programmers tend to be religious about their languages and practices, and are often challenged on their beliefs, so they'll tend to want to preach their ideas to the masses. This reason likely explains this particular article: there was disagreement on the use of NaNs for initialisation, so Walter wanted to express his take on the matter to the masses. I have done similar things in the past, e.g. blogging about my thoughts on immutable in D. Maybe it's all those things plus more. That's my thoughts anyway.
Aug 18 2012
On 8/18/2012 6:51 AM, Peter Alexander wrote:Maybe it's related to the tendency for programmers to be libertarians, which would also explain the whole open source software movement. They want to share knowledge freely, and online articles would be part of that.I find this peculiar, as the open source software movement is frequently associated with communism, not libertarianism. (Although I do think it is much more correct to associate it with libertarianism.)This reason likely explains this particular article: there was disagreement on the use of NaNs for initialisation, so Walter wanted to express his take on the matter to the masses. I have done similar things in the past, e.g. blogging about my thoughts on immutable in D.I write the blogs in Dr. Dobbs because the editors of DDJ have always been very nice to me and supportive of my efforts, going all the way back to my Zortech days. They asked me to write the blogs, and send me nice comments about them. The positive responses they get on reddit encourage me to continue doing them. I wrote the NaN one because there was a lot of interesting discussion on it in the n.g., and so I thought a wider audience would find it interesting as well.
Aug 18 2012
Walter Bright, el 18 de August a las 12:11 me escribiste:On 8/18/2012 6:51 AM, Peter Alexander wrote:Well, free software[1] is closer to communism (or socialism), open source (as in the OSD)[2] is closer to libertarianism. "Open source is a development methodology; free software is a social movement." -- Richard Stallman [1] http://en.wikipedia.org/wiki/The_Free_Software_Definition [2] http://opensource.org/docs/osd -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- Cuando le dije si quería bailar conmigo Se puso a hablar de Jung, de Freud y Lacan Mi idiosincracia le causaba mucha gracia Me dijo al girar la cumbiera intelectualMaybe it's related to the tendency for programmers to be libertarians, which would also explain the whole open source software movement. They want to share knowledge freely, and online articles would be part of that.I find this peculiar, as the open source software movement is frequently associated with communism, not libertarianism. (Although I do think it is much more correct to associate it with libertarianism.)
Aug 20 2012
On 18/08/12 05:03, bearophile wrote:F i L:They write journal articles instead. Producing journal articles have never been of major importance for IT, but they are crucial for science. And if it isn't a new, publishable result, you're more likely to contribute to something like Wikipedia, than to write a blog post. OTOH some people do blog, for example, http://terrytao.wordpress.com/ who is one of the top mathematicians on the planet.Why would it matter what is "normal"?It matters to me because I am curious. Why aren't my friends that work or study chemistry writing free small online articles like my programmer&CS friends do? Maybe it's systematic differences in their brain brain? Or it's just more easy to talk about coding compared to botany and chemistry and making engines? Or maybe programmers don't know what they are doing? Or maybe it's just I am not looking in the right places? :-) Bye, bearophile
Aug 20 2012
Your example: float f; if (condition1) f = 7; ... code ... if (condition2) ++f; is flawed in that condition1 is _required_ to pass in sync with condition2, or you'll get a NaN in the result. In this scenario, you're forced to provide a usable default explicitly no matter what, so your later argument:"This leads to the programmer getting annoyed with false positive error diagnostics, and he'll likely add an =0"doesn't make sense, because he needs to provide a usable value in the first place. This is exactly why I was arguing that explicit assignment to NaN was better for debugging as well. Because a maintenance programmer, that steps in at a later date, would: 1. be less likely to change an explicit assignment to NaN without understand the code fully first. 2. have an easier time tracking down the origin of a NaN error, because variables not explicitly assigned to NaN _can't_ be the culprit. Imagine we have code that looks like: class SomeClass { float foo; float bobDole; float someKind; float barFoo = float.nan; float aVariable; float barBaz; this() { ... lotsa init code ... } } If floats defaulted to 0.0f, then we'd know exactly which variable to analyze in order to find the source of our NaN bug: 'barFoo'. Since we don't have this visual clue, we have to analyze all of them. Of course, we can reverse this by explicitly assigning all, except 'barFoo', to 0.0f, but that's: 1. less convenient to type 2. harder to visually parse to find the potential NaNs 3. inconsistent with 'int' This is how I wish D worked: 1. Functions: void foo() { float f; f ++; // compiler error } void foo() { float f; if (condition1) f = 5; if (condition2) f ++; // compiler error } 2. Structs & Classes: class Foo { float f; // 0.0f void bar() { f++; } // Notice: no constructor defined } void main() { auto foo = new Foo(); foo.bar(); // works fine } Unfortunately, structs don't have default constructors in D. I'm not sure exactly why that is, but if there's some design or performance issue, structs could always work like this instead: 3. Structs: struct Foo { float f; // compiler error } struct Foo { float f = 0; // OK } struct Foo { float f; // OK, if: this() { f = 0; } // set in constructor }
Aug 17 2012
On Saturday, 18 August 2012 at 01:07:43 UTC, F i L wrote:Your example: float f; if (condition1) f = 7; ... code ... if (condition2) ++f; is flawed in that condition1 is _required_ to pass in sync with condition2, or you'll get a NaN in the result.It is not flawed as that is exactly what he said condition1 did until the maintenance programmer made a change which caused this to no longer be in sync with condition2 (most likely fixing a bug as condition1 really should have been false).
Aug 17 2012
On Saturday, 18 August 2012 at 04:44:16 UTC, Jesse Phillips wrote:On Saturday, 18 August 2012 at 01:07:43 UTC, F i L wrote:It's flawed because condition2 relies upon condition1 to function without error. The example, as Walter presented it, is logically describing: float f; if (condition1) { f = 7; if (condition2) f ++; } because the only way Walter's next argument, that "a programmer will haphazardly supply a default value where there _should_ be a NaN", is in error, because if condition2 _does_ rely upon condition1, then there _shouldn't_ be a NaN by the time condition2 is reached, as condition2 _should_ be nested (like above), and the programmer made a logical mistake (which the compiler can warn him about). Remember, NaN in this example is only used as error checking to ensure 'f' is assigned before it's manipulated. If however, condition2 isn't intended to rely upon condition1, then 'f' needs to be explicitly assigned a usable value before condition2, and outside of condition1. Which also negates Walter's "haphazardly assigned" argument, because 'f' _isn't_ intended to be NaN (so assigning to 0.0f makes sense), and condition1 is the only place 'f' is assigned in the example. The only way code like Walter's example is written, is when the coder has made a logical mistake. Which, again, the compiler can warn us about: float f; if (condition1) f = 7; // f _could_ be unassigned, therefor... if (condition2) f ++; // ...should be error Furthermore, in a situation where the value _is_ intended to be NaN (for example, to check 'f' for NaN after condition2) then an explicit assignment to NaN will help document that intent, and help keep a third party from mistakenly assigning it to something else at a later date: float f = float.nan; if (condition1) f = 7; if (condition2) f ++; ...lotsa code... if (f == float.nan) doSomething(); else doSomethingElse(); In this situation, if floats default to NaN and 'f' wasn't explicitly defined, a maintenance programmer might not recognize the last condition, think "gee, I need to set that to a value in case condition1 fails when condition2 does not", and mistakenly assign 'f' a usable value, thus introducing a silent bug.Your example: float f; if (condition1) f = 7; ... code ... if (condition2) ++f; is flawed in that condition1 is _required_ to pass in sync with condition2, or you'll get a NaN in the result.It is not flawed as that is exactly what he said condition1 did until the maintenance programmer made a change which caused this to no longer be in sync with condition2 (most likely fixing a bug as condition1 really should have been false).
Aug 18 2012
F i L:It's flawed because condition2 relies upon condition1 toSome people suggest: http://www.reddit.com/r/programming/comments/yehz4/nans_just_dont_get_no_respect/c5uzt46 Regarding that Reddit thread in general, most people there seem quite ignorant about NaNs, so this little article was a small improvement. Bye, bearophile
Aug 18 2012
On Saturday, 18 August 2012 at 09:32:01 UTC, F i L wrote:It's flawed because condition2 relies upon condition1 to function without error. The example, as Walter presented it, is logically describing: float f; if (condition1) { f = 7; if (condition2) f ++; }This greatly changes the semantics of the code. I do not disagree that the example indicates the original programmer is likely wrong and needs to improve the description of his intent. What I disagree on is that it is that complaining that f might not be initialized will force the programmer to think and address the true issue. It is also taking the example at face value. The complexity of the relationship could be harder too see (I don't know what that would be), and somewhere else where condition1 is set there could be code: auto condition1 = getmevalue(); enforce(condition1 && condition2, "Huston this is the problem!"); Someone is probably at fault and the one addressing the issue may still get it wrong; if it is the second programmer hopefully they will have more information about what they need as they were the ones changing the semantics of the code.
Aug 18 2012
On Saturday, 18 August 2012 at 14:29:12 UTC, Jesse Phillips wrote:On Saturday, 18 August 2012 at 09:32:01 UTC, F i L wrote:I agree, and that's my point here. The original example is an erroneous presupposition that leads to faulty conclusions. If the compiler warned against this error the programmer would likely fix the code to a state which prevents the potential bug this example was originally intended to illustrate.It's flawed because condition2 relies upon condition1 to function without error. The example, as Walter presented it, is logically describing: float f; if (condition1) { f = 7; if (condition2) f ++; }This greatly changes the semantics of the code. I do not disagree that the example indicates the original programmer is likely wrong and needs to improve the description of his intent.What I disagree on is that it is that complaining that f might not be initialized will force the programmer to think and address the true issue. It is also taking the example at face value. The complexity of the relationship could be harder too see (I don't know what that would be),I too, don't know of any examples where defaulting to NaN would prevent an error where static analysis would not, though I'm always open to argument. Given the benefits of static analysis and defaulting to 0.0f for class members (which I listed in previous posts), I see that position as the one with demonstrable benefit.and somewhere else where condition1 is set there could be code: auto condition1 = getmevalue(); enforce(condition1 && condition2, "Huston this is the problem!");I don't see how this changes the situation with NaN vs. static analysis.
Aug 18 2012
On Saturday, 18 August 2012 at 18:06:12 UTC, F i L wrote:If the compiler warned against this error the programmer would likely fix the code to a state which prevents the potential bug this example was originally intended to illustrate.It is this statement that indicates you didn't fully comprehend what was written in the article. It is likely that the author will initialize f to a value. In which case you have increased the likelyhood that the incorrect value of 0 will be assigned instead of NAN. So I do not agree that it is likely he will fix the code in a manner that would prevent this bug from happening.
Aug 18 2012
On Sat, 18 Aug 2012 23:12:10 +0200 "Jesse Phillips" <jessekphillips+D gmail.com> wrote:On Saturday, 18 August 2012 at 18:06:12 UTC, F i L wrote:against, and the result never involved getting annoyed and blindly tossing in an "=0".If the compiler warned against this error the programmer would likely fix the code to a state which prevents the potential bug this example was originally intended to illustrate.It is this statement that indicates you didn't fully comprehend what was written in the article. It is likely that the author will initialize f to a value. In which case you have increased the likelyhood that the incorrect value of 0 will be assigned instead of NAN. So I do not agree that it is likely he will fix the code in a manner that would prevent this bug from happening.
Aug 18 2012
On 8/18/2012 7:27 PM, Nick Sabalausky wrote:against, and the result never involved getting annoyed and blindly tossing in an "=0".I've seen this problem in the real world, even though you don't make such mistakes.
Aug 18 2012
On Sat, 18 Aug 2012 20:44:52 -0700 Walter Bright <newshound2 digitalmars.com> wrote:On 8/18/2012 7:27 PM, Nick Sabalausky wrote:I've seen lots of stupid shit in production code. I've seen a data-loading function named "save". So which foot should we shoot off in our fear of that real-world mistake? And yes, yes, yes, I know AND AGREE that designing a language to help prevent mistakes is the right things to do, but I strongly believe you've gotten it backwards in this specific case (nothing personal, of course). I think you're: 1. Severely overstating the problem of "blindly toss in a =0" possibly-initited value usage. (statically/conservatively ensure things can't be accessed without being explicitly inited), and I'm convinced the benefits of the static checks easily outweigh the fear of a knee-jerk "=0".against, and the result never involved getting annoyed and blindly tossing in an "=0".I've seen this problem in the real world, even though you don't make such mistakes.
Aug 18 2012
On 8/18/2012 9:21 PM, Nick Sabalausky wrote:(statically/conservatively ensure things can't be accessed without being explicitly inited), and I'm convinced the benefits of the static checks easily outweigh the fear of a knee-jerk "=0".I'm less willing to throw default initialization out - I like it & rely on it. defined types.
Aug 18 2012
On 2012-08-19 05:54:49 +0000, Walter Bright <newshound2 digitalmars.com> said:On 8/18/2012 9:21 PM, Nick Sabalausky wrote:I like default initialization too, and I rely on it. By that I mean that all the time I write "size_t count;" and assume it'll be default initialized to zero. I like it because it's less typing and it's simple: if I don't assign anything it's zero. I can't do that for floats or chars, because the default initialization gives me a unusable than default initialization to a bogus value because they catch the problem at compile time. But on the other side I'd rather not give up on integer default initialization to zero, as I actually prefer this over everything else. So Walter, which default initialization do you like an rely on? As I said, personally, I'd have everything initialized to zero by default. But at this point you can't really change this even if you want to: some program somewhere might rely on float being initialized to NaN by default and might start to give erroneous results if you change the default. (Notice the irony?) -- Michel Fortin michel.fortin michelf.ca http://michelf.ca/(statically/conservatively ensure things can't be accessed without being explicitly inited), and I'm convinced the benefits of the static checks easily outweigh the fear of a knee-jerk "=0".I'm less willing to throw default initialization out - I like it & rely including for user defined types.
Aug 19 2012
On Sunday, 19 August 2012 at 14:14:00 UTC, Michel Fortin wrote:On 2012-08-19 05:54:49 +0000, Walter Bright <newshound2 digitalmars.com> said:The problem with implicit initialisation to zero is that it is indistinguishable from simply forgetting to initialise the value. There's three scenarios here: 1. You intentionally relied on implicit initialisation: GOOD. 2. You forgot, 0 wasn't what you wanted, but the error shows up quickly: NOT BAD 3. You forgot, 0 wasn't what you wanted, but the error is subtle/rare: BAD bugs have the potential to be monsters, and in my opinion, avoiding them is far more important than saving a couple of keystrokes in initialisation. There's two solutions: 1. Conservative compile-time error on uninitialised variables. Personally, I'd prefer option 1. Walter's argument is that this "leads to the programmer getting annoyed with false positive error diagnostics, and he'll likely add an =0", which is true, but in my opinion this scenario is quite rare to start with, and it's even more rare that 0 isn't actually the right initialisation value, and even then it's only a problem if the introduced bug is hard to reproduce. I find it more likely that the NaN will go unnoticed and cause rare bugs.On 8/18/2012 9:21 PM, Nick Sabalausky wrote:I like default initialization too, and I rely on it. By that I mean that all the time I write "size_t count;" and assume it'll be default initialized to zero. I like it because it's less typing and it's simple: if I don't assign anything it's zero. I can't do that for floats or chars, because the default conservative flow analysis errors are better than default initialization to a bogus value because they catch the problem at compile time. But on the other side I'd rather not give up on integer default initialization to zero, as I actually prefer this over everything else. So Walter, which default initialization do you like an rely on? As I said, personally, I'd have everything initialized to zero by default. But at this point you can't really change this even if you want to: some program somewhere might rely on float being initialized to NaN by default and might start to give erroneous results if you change the default. (Notice the irony?)(statically/conservatively ensure things can't be accessed without being explicitly inited), and I'm convinced the benefits of the static checks easily outweigh the fear of a knee-jerk "=0".I'm less willing to throw default initialization out - I like initialization, including for user defined types.
Aug 19 2012
On 8/19/2012 8:18 AM, Peter Alexander wrote:Personally, I'd prefer option 1. Walter's argument is that this "leads to the programmer getting annoyed with false positive error diagnostics, and he'll likely add an =0", which is true, but in my opinion this scenario is quite rare to start with, and it's even more rare that 0 isn't actually the right initialisation value, and even then it's only a problem if the introduced bug is hard to reproduce.Rare, yes, it's rare. But it's really ugly and hard to find when it does happen.I find it more likely that the NaN will go unnoticed and cause rare bugs.NaNs in your output are pretty obvious. For example, if your accounting program prints "NAN" for the amount on the payroll cheques, someone is guaranteed to notice. But if it's a few cents off in your disfavor, it might take you years to discover there's a problem. Critical systems also would find a NaN command a lot easier to detect than an off-by-two command, and would be able to shut down and engage the backup.
Aug 19 2012
I was against nan being the dafault value, but now I that I think about it, it is useful (for the reasons in the article).
Aug 19 2012
On Sunday, 19 August 2012 at 22:22:28 UTC, Walter Bright wrote:The problem is that it's easy for even NaN's to be filtered out. float x = 0.0f; float y; // oops float z = min(x, y); // NaN has disappeared, unnoticed! My argument is that conservative compile time errors on uninitialised variables are more likely to catch these errors.I find it more likely that the NaN will go unnoticed and cause rare bugs.NaNs in your output are pretty obvious. For example, if your accounting program prints "NAN" for the amount on the payroll cheques, someone is guaranteed to notice. But if it's a few cents off in your disfavor, it might take you years to discover there's a problem. Critical systems also would find a NaN command a lot easier to detect than an off-by-two command, and would be able to shut down and engage the backup.
Aug 20 2012
On Monday, 20 August 2012 at 19:28:33 UTC, Peter Alexander wrote:On Sunday, 19 August 2012 at 22:22:28 UTC, Walter Bright wrote:I just tried this: float a, b = 10; writeln(min(a, b), ", ", fmin(a, b)); Result: nan, 10 I think that is incorrect - both should give NaN. The scientific viz software I use at work returns NaN for any numerical operation on NaN values, means, smoothing, etc.The problem is that it's easy for even NaN's to be filtered out. float x = 0.0f; float y; // oops float z = min(x, y); // NaN has disappeared, unnoticed! My argument is that conservative compile time errors on uninitialised variables are more likely to catch these errors.I find it more likely that the NaN will go unnoticed and cause rare bugs.NaNs in your output are pretty obvious. For example, if your accounting program prints "NAN" for the amount on the payroll cheques, someone is guaranteed to notice. But if it's a few cents off in your disfavor, it might take you years to discover there's a problem. Critical systems also would find a NaN command a lot easier to detect than an off-by-two command, and would be able to shut down and engage the backup.
Aug 20 2012
On Monday, 20 August 2012 at 20:21:12 UTC, cal wrote:I just tried this: float a, b = 10; writeln(min(a, b), ", ", fmin(a, b)); Result: nan, 10 I think that is incorrect - both should give NaN. The scientific viz software I use at work returns NaN for any numerical operation on NaN values, means, smoothing, etc.It's tricky. The only way (that I'm aware of) to get it to return NaN is to explicitly test for NaN, introducing overhead that is unnecessary 99.9% of the time. Unfortunately this is one of those situations where D's design goals of efficiency and safety are at odds. You can't have it both ways.
Aug 20 2012
Peter Alexander:It's tricky. The only way (that I'm aware of) to get it to return NaN is to explicitly test for NaN, introducing overhead that is unnecessary 99.9% of the time. Unfortunately this is one of those situations where D's design goals of efficiency and safety are at odds. You can't have it both ways.Few possibilities: 1) Add a second NaN-aware function pair nmax()/nmin(); 2) Add a debug{} inside min()/max(), where NaNs are managed; 3) Introduce a if(version=NaNAware){} block inside the normal max()/min() and other Phobos functions, to be used when you want more NaN-correct results. I prefer the third idea, but this probably requires a recompilation of Phobos. Bye, bearophile
Aug 20 2012
On 20/08/12 22:21, cal wrote:On Monday, 20 August 2012 at 19:28:33 UTC, Peter Alexander wrote:No, it's the other way around. The IEEE 754 standard defines min(x, NaN) == min(NaN, x) == x. According to the C standard, fmin() should be returning 10, as well. There is a bug in fmin(). However min() and max() are extremely unusual in this respect. Almost everything else involving a NaN returns NaN.On Sunday, 19 August 2012 at 22:22:28 UTC, Walter Bright wrote:I just tried this: float a, b = 10; writeln(min(a, b), ", ", fmin(a, b)); Result: nan, 10 I think that is incorrect - both should give NaN. The scientific viz software I use at work returns NaN for any numerical operation on NaN values, means, smoothing, etc.The problem is that it's easy for even NaN's to be filtered out. float x = 0.0f; float y; // oops float z = min(x, y); // NaN has disappeared, unnoticed! My argument is that conservative compile time errors on uninitialised variables are more likely to catch these errors.I find it more likely that the NaN will go unnoticed and cause rare bugs.NaNs in your output are pretty obvious. For example, if your accounting program prints "NAN" for the amount on the payroll cheques, someone is guaranteed to notice. But if it's a few cents off in your disfavor, it might take you years to discover there's a problem. Critical systems also would find a NaN command a lot easier to detect than an off-by-two command, and would be able to shut down and engage the backup.
Aug 21 2012
On Tuesday, 21 August 2012 at 08:15:10 UTC, Don Clugston wrote:No, it's the other way around. The IEEE 754 standard defines min(x, NaN) == min(NaN, x) == x. According to the C standard, fmin() should be returning 10, as well. There is a bug in fmin(). However min() and max() are extremely unusual in this respect. Almost everything else involving a NaN returns NaN.I did not know that. It seems like a not-so-useful rule but I guess they have their reasons. Note that in my example, fmin() _did_ return 10 - it was min() that returned NaN...
Aug 21 2012
On Monday, 20 August 2012 at 19:28:33 UTC, Peter Alexander wrote: [cut]The problem is that it's easy for even NaN's to be filtered out. float x = 0.0f; float y; // oops float z = min(x, y); // NaN has disappeared, unnoticed!In theory, one could prevent this by setting the floating point control word to trigger a trap when reading a NaN which I think *should* be the default. Unfortunately it doesn't seem to work, there is an FPE in the code below, where it shouldn't. Then again, the online compiler I've tried is very old: dmd-2.042.import std.stdio, std.math, std.algorithm; int main() { FloatingPointControl fpc; fpc.enableExceptions(FloatingPointControl.severeExceptions); float x = 0.0f; float y; // oops y=1; float z = min(x, y); writeln("min x,y=",z); return 0; } <<
Aug 21 2012
On Sat, 18 Aug 2012 06:44:12 +0200 "Jesse Phillips" <jessekphillips+D gmail.com> wrote:On Saturday, 18 August 2012 at 01:07:43 UTC, F i L wrote:If that's the case, then the code is far too damn fragile in the first place. This: float f; if (condition1) f = 7; Is bad fucking code, period. I'd expect *ANY* usage of f after that (except, of course, a plain assignment to it) to be flagged as an error. That's because *even if* f isn't technically used without assignment, it still indicates that somebody didn't think their shit through and may already be hiding a bug (in which case they're damnned lucky it's a float instead of an int) - and even if not, then it's still too damn fragile anyway and *will* likely wind up creating a bug once someone goes and touches that code. FWIW, Last time we debated this on the NG, this was the point where Walter got stuck on the irrelevant "But it's not garbage-inited like C!" strawman. I hope we can do better this time.Your example: float f; if (condition1) f = 7; ... code ... if (condition2) ++f; is flawed in that condition1 is _required_ to pass in sync with condition2, or you'll get a NaN in the result.It is not flawed as that is exactly what he said condition1 did until the maintenance programmer made a change which caused this to no longer be in sync with condition2 (most likely fixing a bug as condition1 really should have been false).
Aug 18 2012
On 8/18/2012 7:36 PM, Nick Sabalausky wrote:If that's the case, then the code is far too damn fragile in the first place. This: float f; if (condition1) f = 7; Is bad fucking code, period. I'd expect *ANY* usage of f after that (except, of course, a plain assignment to it) to be flagged as an error. That's because *even if* f isn't technically used without assignment, it still indicates that somebody didn't think their shit through and may already be hiding a bug (in which case they're damnned lucky it's a float instead of an int) - and even if not, then it's still too damn fragile anyway and *will* likely wind up creating a bug once someone goes and touches that code. FWIW, Last time we debated this on the NG, this was the point where Walter got stuck on the irrelevant "But it's not garbage-inited like C!" strawman. I hope we can do better this time.With respect, I think that you are conflating two different questions. If the question is, "should static checking reject this code as flawed?", then NaN is irrelevant, and a strawman, yes. But if the question is, "is default-initializing to NaN better than default-initializing to garbage?", then it's entirely on point. (And that is the topic of this thread.) Scala or what have you) could do a complete static check of the code. As a practical matter, today's compiler technology cannot. (And if it could, you'd get complaints about compile times... <grin/>) Since the flaw may not be detected statically at compile time, it's nice to know that NaN will detect it at runtime (in the same sense that a minefield "detects" an intruder). Consider how useful *integer* NaN is. Oh, you didn't realize that, when you used zero, or minus one, or 0xFFFF or its moral equivalents, to flag an error or exceptional condition on a function that returns what is normally a number, that you were hand-rolling an integer NaN? For that matter, wouldn't it be nice to have a Boolean NaN? (not "true", not "false", but "not yet decided") Except of course that zero, and one, and minus one, and all-bits-set are all extremely common and useful *arithmetic* values, and all too likely to be returned legitimately. So having a hardware NaN in floating point, particularly one that "taints" all future results it participates in, and further one that can (by definition) never be a legitimate number, is genius. And having Walter design D to take advantage of it is... well, perhaps not genius, but damned smart. I'll build my bricks with Walter's straw, any day.
Aug 18 2012
OT: On Sunday, 19 August 2012 at 03:16:39 UTC, Davidson Corry wrote:For that matter, wouldn't it be nice to have a Boolean NaN? (not "true", not "false", but "not yet decided")enum BOOL { TRUE, FALSE, FILE_NOT_FOUND } http://thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx
Aug 18 2012
On 8/18/2012 8:31 PM, Adam D. Ruppe wrote:enum BOOL { TRUE, FALSE, FILE_NOT_FOUND }I used to work with digital electronics. There, "boolean" logic actually had 4 states: True False Don't Know Don't Care
Aug 18 2012
On Sat, 18 Aug 2012 20:52:01 -0700 Walter Bright <newshound2 digitalmars.com> wrote:On 8/18/2012 8:31 PM, Adam D. Ruppe wrote:enum BOOL { TRUE, FALSE, FILE_NOT_FOUND }I used to work with digital electronics. There, "boolean" logic actually had 4 states: True False Don't Know Don't CareIt sounds like it's some EE joke, but yea, strange as it seems, not only is there really a "Don't care", but it's actually useful (for not wasting excess silicon/logic-gates on states that can't (or shouldn't) ever occur - it means "ehh, just make this whatever value would require the fewest logic gates since it won't actually matter anyway"). I only ever dabbled with some very rudimentary digital EE, I'm still a bit of a novice, but it's pretty damn cool stuff.
Aug 18 2012
On 8/18/2012 9:33 PM, Nick Sabalausky wrote:It sounds like it's some EE joke, but yea, strange as it seems, not only is there really a "Don't care", but it's actually usefulYup, it turns out that all 4 states are very useful.
Aug 18 2012
On Sun, 19 Aug 2012 05:52:01 +0200, Walter Bright <newshound2 digitalmars.com> wrote:On 8/18/2012 8:31 PM, Adam D. Ruppe wrote:Like someone on Reddit mentioned, VHDL has 9 boolean states: 'U': uninitialized. This signal hasn't been set yet. 'X': unknown. Impossible to determine this value/result. '0': logic 0 '1': logic 1 'Z': High Impedance 'W': Weak signal, can't tell if it should be 0 or 1. 'L': Weak signal that should probably go to 0 'H': Weak signal that should probably go to 1 '-': Don't care. -- Simenenum BOOL { TRUE, FALSE, FILE_NOT_FOUND }I used to work with digital electronics. There, "boolean" logic actually had 4 states: True False Don't Know Don't Care
Aug 19 2012
On Sat, 18 Aug 2012 20:16:37 -0700 Davidson Corry <davidsoncorry comcast.net> wrote:On 8/18/2012 7:36 PM, Nick Sabalausky wrote:No offense taken (or intended), but I think you're conflating the different branches of the discussion. The "NaN-initing better than garbage/zero-initing" was a key point of the OP, yes, but not of all branches of discussion, and not the only point in the article either. Please reread the thread and notice that the branch I was replying to was directed specifically at this section of the article: -------------------------------------- Given the code: float f; if (condition) ++f; the user writes "in language X, the compiler complains on line 3 saying that f is used without being initialized. Isn't that a better solution?" For that example, it probably is a better solution. But consider: float f; if (condition1) f = 7; ... code ... if (condition2) ++f; [Goes on attempting to build a case against the static checking] -------------------------------------- So yes, the OP *IS* claiming "NaN-initing > conservative static checks" and that is what this branch of the thread, including the post I directly replied to, was directly addressing.If that's the case, then the code is far too damn fragile in the first place. This: float f; if (condition1) f = 7; Is bad fucking code, period. I'd expect *ANY* usage of f after that (except, of course, a plain assignment to it) to be flagged as an error. That's because *even if* f isn't technically used without assignment, it still indicates that somebody didn't think their shit through and may already be hiding a bug (in which case they're damnned lucky it's a float instead of an int) - and even if not, then it's still too damn fragile anyway and *will* likely wind up creating a bug once someone goes and touches that code. FWIW, Last time we debated this on the NG, this was the point where Walter got stuck on the irrelevant "But it's not garbage-inited like C!" strawman. I hope we can do better this time.With respect, I think that you are conflating two different questions. If the question is, "should static checking reject this code as flawed?", then NaN is irrelevant, and a strawman, yes. But if the question is, "is default-initializing to NaN better than default-initializing to garbage?", then it's entirely on point. (And that is the topic of this thread.)or Scala or what have you) could do a complete static check of the code. As a practical matter, today's compiler technology cannot. (And if it could, you'd get complaints about compile times... <grin/>)Actually, I disagree. I want a static check, but I *don't* want it to be complete. Largely because of the difficulty of doing so and the compile times, yes, BUT also because (as I already said) code such as this: float f; if (condition) ++f; // Complex stuff that may involve f in certain codepaths Is *already* fragile and bad, and could easily hide/generate bugs even with NaN. In fact, there's a reasonable chance it may already be a bug, again even with NaN. And even with NaN, it would still be much better to just get an error for the whole damn thing: "ERROR: This is screwy fucking code. Even if it's not technically buggy right now, which is questionable anyway, it can easily become a bug if it gets altered without being very, VERY careful. So go back and rewrite it to not be so damned fragile."Since the flaw may not be detected statically at compile time, it's nice to know that NaN will detect it at runtime (in the same sense that a minefield "detects" an intruder).I'm advocating conservative static checking. It WILL be detected at compile-time (along with some false positives, but I've been arguing these are GOOD false positives, or *at least* perfectly acceptable).Consider how useful *integer* NaN is. Oh, you didn't realize that,Please don't put words in my mouth. I've advocated in past discussions for making 'int.init' be 0xDEADBEEF or 0x69696969 as a "next-best thing" for when (as with D) static checking isn't performed.when you used zero, or minus one, or 0xFFFF or its moral equivalents, to flag an error or exceptional condition on a function that returns what is normally a number, that you were hand-rolling an integer NaN? For that matter, wouldn't it be nice to have a Boolean NaN? (not "true", not "false", but "not yet decided") Except of course that zero, and one, and minus one, and all-bits-set are all extremely common and useful *arithmetic* values, and all too likely to be returned legitimately. So having a hardware NaN in floating point, particularly one that "taints" all future results it participates in, and further one that can (by definition) never be a legitimate number, is genius. And having Walter design D to take advantage of it is... well, perhaps not genius, but damned smart.Right. But what's *even smarter* than that, is just eliminating the whole f***** problem at compile-time. Walter has specifically argued against the wisdom of that on various occasions (including in this article), and what I'm saying is that I don't buy *that* reasoning or its conclusion. (And then I went on and bitched about a previous discussion where he kept trying to use "NaN/0-init > garbage-init" as a rebuttal to my completely *different* argument of "static checks > NaN/0-init". Hence the "strawman".)
Aug 18 2012
On 8/18/2012 9:05 PM, Nick Sabalausky wrote:No offense taken (or intended), but I think you're conflating the different branches of the discussion.I'm glad. And it's entirely likely that I missed something. I didn't read the whole thread, I was just replying to your one message. Lazy...The "NaN-initing better than garbage/zero-initing" was a key point of the OP, yes, but not of all branches of discussion, and not the only point in the article either. Please reread the thread and notice that the branch I was replying to was directed specifically at this section of the article: -------------------------------------- Given the code: float f; if (condition) ++f; the user writes "in language X, the compiler complains on line 3 saying that f is used without being initialized. Isn't that a better solution?" For that example, it probably is a better solution. But consider: float f; if (condition1) f = 7; ... code ... if (condition2) ++f; [Goes on attempting to build a case against the static checking] -------------------------------------- So yes, the OP *IS* claiming "NaN-initing > conservative static checks" and that is what this branch of the thread, including the post I directly replied to, was directly addressing.Fair enough. I agree with you that the claim is in error -- not because I think the > operator should be pointing <, but because the two things are unrelated and shouldn't be compared. One is a compile-time check, the other a runtime minefield. One is a logic analysis, the other an out-of-domain value test. They are not XOR -- *both* should be used. (And some of us clever programmers will slip bogus programs past both of them anyway...)So true. But the only technology I have found to date capable of such insight is a good code review. And a good reviewer who is willing to take the time and analyze my code in depth (and then patiently and politely get past my mule-headed stubbornness and get me to see what he's saying) is a treasure beyond price. Man, if you can package *that* in a compiler, I'm buyin'!or Scala or what have you) could do a complete static check...Actually, I disagree. I want a static check, but I *don't* want it to be complete. Largely because of the difficulty of doing so and the compile times, yes, BUT also because (as I already said) code such as this: float f; if (condition) ++f; // Complex stuff that may involve f in certain codepaths Is *already* fragile and bad, and could easily hide/generate bugs even with NaN. In fact, there's a reasonable chance it may already be a bug, again even with NaN. And even with NaN, it would still be much better to just get an error for the whole damn thing: "ERROR: This is screwy fucking code. Even if it's not technically buggy right now, which is questionable anyway, it can easily become a bug if it gets altered without being very, VERY careful. So go back and rewrite it to not be so damned fragile."I apologize. I did not mean that *you personally* were advocating specific "not an integer" values like -1. I meant the generic "you" as in many APIs that I am sure you are familiar with. Certainly there may be applications where a human-recognizable "dead beef" flag works well... and others where you don't want to drop a "not a value" value into the middle of a useful range. (0xDEADBEEF is not a useful value, but 0xDEADBEEE and 0xDEADBEF0 are??) What I was trying to say was that programmers re-invent the "not a valid value" trick all the time. For example, the Unicode Consortium defines the code point 0xFFFE to be an invalid character, and thus allows tricks like the Byte Order Mark. In my own specialty of Windows installer work, a zero exit code marks "success" and a non-zero exit is "failure"... except that the special values of decimal 3010 and (archaically) 8192 flag "success but reboot required to complete the install". NULL and nullptr are special values for C/C++. And so on. I have needed a flag to indicate a Boolean with a one-time initialization often enough to have written a small class to encapsulate the True|False|NotYetSet behavior. And it lacks rigor. For instance, it does not have the "taints all downstream expressions" behavior that floating NaN does. One of these days I will rewrite it correctly and add it to a library.Consider how useful *integer* NaN is. Oh, you didn't realize that,Please don't put words in my mouth. I've advocated in past discussions for making 'int.init' be 0xDEADBEEF or 0x69696969 as a "next-best thing" for when (as with D) static checking isn't performed.OK. Well, you may need to write your own compiler, then. You and Walter may be enlightened enough to gain insight through earnest reason together. Me, you usually have to hit me over the head with something heavy a couple of times before I get your point. <grin> Ouch. -- Davidson...So having a hardware NaN in floating point, particularly one that "taints" all future results it participates in, and further one that can (by definition) never be a legitimate number, is genius. And having Walter design D to take advantage of it is... well, perhaps not genius, but damned smart.Right. But what's *even smarter* than that, is just eliminating the whole problem at compile-time. Walter has specifically argued against the wisdom of that on various occasions (including in this article), and what I'm saying is that I don't buy *that* reasoning or its conclusion. (And then I went on and bitched about a previous discussion where he kept trying to use "NaN/0-init > garbage-init" as a rebuttal to my completely *different* argument of "static checks > NaN/0-init". Hence the "strawman".)
Aug 20 2012
I remember you (Walter) or somebody else talking about signaling NaNs before, but I don't remember many details about it. Does D use them? Is this an answer to the Reddit commenter who mentioned immediately throwing an exception?
Aug 17 2012
On 8/17/2012 5:03 PM, Walter Bright wrote:Our discussion on this in the last few days inspired me to write a blog post about it: http://www.reddit.com/r/programming/comments/yehz4/nans_just_dont_get_no_respect/ http://www.drdobbs.com/cpp/nans-just-dont-get-no-respect/240005723http://news.ycombinator.com/item?id=4399635
Aug 17 2012
Another sub-thread that shows a very important thing, that's missing: http://www.reddit.com/r/programming/comments/yehz4/nans_just_dont_get_no_respect/c5v1u0y Bye, bearophile
Aug 18 2012
On 8/18/2012 2:16 PM, bearophile wrote:Another sub-thread that shows a very important thing, that's missing: http://www.reddit.com/r/programming/comments/yehz4/nans_just_dont_get_no_respect/c5v1u0yOh come on. That's called a "user defined type." struct OptionType { private T m_value; property T value() { check m_value; return m_value; } }
Aug 18 2012
Walter Bright:Oh come on. That's called a "user defined type."This D code compiles and it throws an "Enforcement failed" Exception at runtime: import std.typecons: Nullable; void main() { Nullable!int x; int y = x; } With a different type system the compiler makes sure at compile-time that x is not empty (this means the compiler makes sure in no code paths x is used before testing it contains something), avoiding the run-time exception. Bye, bearophile
Aug 19 2012
On 8/19/2012 5:08 AM, bearophile wrote:With a different type system the compiler makes sure at compile-time that x is not empty (this means the compiler makes sure in no code paths x is used before testing it contains something), avoiding the run-time exception.That's called disabling the default constructor with disable.
Aug 19 2012
On Sun, 19 Aug 2012 22:18:37 +0200, Walter Bright <newshound2 digitalmars.com> wrote:On 8/19/2012 5:08 AM, bearophile wrote:Nope. What bearophile is talking about is something more akin to this, I think: Nullable!int a; int x = a; // Compile-time error: a might be null! if ( a ) { int y = a; // 's fine, we know it's not null. } -- SimenWith a different type system the compiler makes sure at compile-time that x is not empty (this means the compiler makes sure in no code paths x is used before testing it contains something), avoiding the run-time exception.That's called disabling the default constructor with disable.
Aug 19 2012
On 8/19/2012 2:41 PM, Simen Kjaeraas wrote:Nullable!int a; int x = a; // Compile-time error: a might be null! if ( a ) { int y = a; // 's fine, we know it's not null. }You'd want the int to be the non-nullable type. You can do this with D's type system. Each state would be a different type, with user defined conversions between them.
Aug 19 2012
On Sun, 19 Aug 2012 14:08:17 +0200, bearophile <bearophileHUGS lycos.com> wrote:Walter Bright:We could define a Nullable!T that does not allow access to the payload value, and only give that access inside a special function, like pattern matching in other languages: Nullable!int a; int n = a.match!( (int x) => x, (None n) => 0 ); -- SimenOh come on. That's called a "user defined type."This D code compiles and it throws an "Enforcement failed" Exception at runtime: import std.typecons: Nullable; void main() { Nullable!int x; int y = x; } With a different type system the compiler makes sure at compile-time that x is not empty (this means the compiler makes sure in no code paths x is used before testing it contains something), avoiding the run-time exception.
Aug 19 2012
On 8/17/12 8:03 PM, Walter Bright wrote:Our discussion on this in the last few days inspired me to write a blog post about it: http://www.reddit.com/r/programming/comments/yehz4/nans_just_dont_get_no_respect/Homerun. Nice!! Andrei
Aug 18 2012
On Friday, August 17, 2012 17:03:13 Walter Bright wrote:Our discussion on this in the last few days inspired me to write a blog post about it: http://www.reddit.com/r/programming/comments/yehz4/nans_just_dont_get_no_res pect/ http://www.drdobbs.com/cpp/nans-just-dont-get-no-respect/240005723FWIW, I'm very surprised by how negatively many programmers seem to react to NaN. I think that how D handles it is great. IMHO, if anything, it's the fact that we don't have something similar for integral values which is problematic, not the fact that floating point values default initialize to NaN. - Jonathan M Davis
Aug 18 2012
On Sat, 18 Aug 2012 21:12:33 -0700 Jonathan M Davis <jmdavisProg gmx.com> wrote:FWIW, I'm very surprised by how negatively many programmers seem to react to NaN. I think that how D handles it is great.Yea, it's kind of like Unicode: ASCII is much simpler and therefore far more enticing. But unfortunately we have to deal with reality and reality dictates that NaNs and non-ASCII chars exist and must be taken into consideration.
Aug 18 2012
Am 19.08.2012 06:12, schrieb Jonathan M Davis:On Friday, August 17, 2012 17:03:13 Walter Bright wrote:i think many of these programmers seems to think that D is introducing this NaN-Type ...Our discussion on this in the last few days inspired me to write a blog post about it: http://www.reddit.com/r/programming/comments/yehz4/nans_just_dont_get_no_res pect/ http://www.drdobbs.com/cpp/nans-just-dont-get-no-respect/240005723FWIW, I'm very surprised by how negatively many programmers seem to react to NaN. I think that how D handles it is great.
Aug 18 2012
On 8/19/2012 12:12 AM, dennis luehring wrote:Am 19.08.2012 06:12, schrieb Jonathan M Davis:Nobody knows how floats work, without being locked in a closet for a at least a week and told to change their doubles back into floats and fix their code, since thats where 99% of precision problems actually come from.On Friday, August 17, 2012 17:03:13 Walter Bright wrote:i think many of these programmers seems to think that D is introducing this NaN-Type ...Our discussion on this in the last few days inspired me to write a blog post about it: http://www.reddit.com/r/programming/comments/yehz4/nans_just_dont_get_no_res pect/ http://www.drdobbs.com/cpp/nans-just-dont-get-no-respect/240005723FWIW, I'm very surprised by how negatively many programmers seem to react to NaN. I think that how D handles it is great.
Aug 18 2012
On 8/18/2012 11:21 PM, Sean Cavanaugh wrote:Nobody knows how floats work, without being locked in a closet for a at least a week and told to change their doubles back into floats and fix their code, since thats where 99% of precision problems actually come from.I was forced to figure out how they work in excruciating detail, as I had to write an emulator in case the user didn't have an 8087. Actually, that knowledge has served me well.
Aug 19 2012
On Sun, 19 Aug 2012 01:21:03 -0500 Sean Cavanaugh <WorksOnMyMachine gmail.com> wrote:Nobody knows how floats work, without being locked in a closet for a at least a week and told to change their doubles back into floats and fix their code, since thats where 99% of precision problems actually come from.Sorry, I don't understand, where are you saying 99% of precision problems come from?
Aug 19 2012
On 8/20/2012 12:41 AM, Nick Sabalausky wrote:On Sun, 19 Aug 2012 01:21:03 -0500 Sean Cavanaugh<WorksOnMyMachine gmail.com> wrote:Chaining algorithms together without regard to how the floats are propagated through the system. Also, accumulating lots of values with addition and subtraction can be problematic, as can subtracting two values to near-zero values also leaves you with a most of the error. There is a pretty classic example in 3d graphics: the transform from object space to world space to projection space. Even if these matrices are combined, your geometry can be transformed a very large distance from the world origin and lose a lot of precision in the process. The way to fight this is to use camera instead of world space as much as possible. If you don't do this all the vertices on all the meshes in your world snap to different values at varying rates when they move or the camera moves, causing one of the main forms of z-fighting. Plus the further you get from your world origin the worse things get, which makes building something on the scale of an open-world game rather difficult.Nobody knows how floats work, without being locked in a closet for a at least a week and told to change their doubles back into floats and fix their code, since thats where 99% of precision problems actually come from.Sorry, I don't understand, where are you saying 99% of precision problems come from?
Aug 20 2012
On Sunday, 19 August 2012 at 05:13:09 UTC, dennis luehring wrote:Am 19.08.2012 06:12, schrieb Jonathan M Davis:Yes, I got this impression as well. What a sad state of affairs.On Friday, August 17, 2012 17:03:13 Walter Bright wrote:i think many of these programmers seems to think that D is introducing this NaN-Type ...Our discussion on this in the last few days inspired me to write a blog post about it: http://www.reddit.com/r/programming/comments/yehz4/nans_just_dont_get_no_res pect/ http://www.drdobbs.com/cpp/nans-just-dont-get-no-respect/240005723FWIW, I'm very surprised by how negatively many programmers seem to react to NaN. I think that how D handles it is great.
Aug 19 2012
On 8/19/2012 4:48 AM, Peter Alexander wrote:Yes, I got this impression as well. What a sad state of affairs.Yup. NaNs just don't get no respect, I tell ya! No respect at all!
Aug 19 2012
"Walter Bright" wrote in message news:k0rhp5$2fud$2 digitalmars.com... On 8/19/2012 4:48 AM, Peter Alexander wrote:Yes, I got this impression as well. What a sad state of affairs.Yup. NaNs just don't get no respect, I tell ya! No respect at all! NaNs are the Rodney Dangerfield of D...
Aug 19 2012
On 08/17/2012 08:03 PM, Walter Bright wrote:Our discussion on this in the last few days inspired me to write a blog post about it: http://www.reddit.com/r/programming/comments/yehz4/nans_just_dont_get_no_respect/ http://www.drdobbs.com/cpp/nans-just-dont-get-no-respect/240005723Walter, I know you like to make the easy thing the right thing. I like this notion myself. So instead of writing float f; if (condition1) f = 7; ... code ... if (condition2) ++f; is there any way we can make it easier to write void someCode() { ... code ... } float f; if ( condition ) { f = 7; someCode(); ++f; } else someCode(); assuming that condition2 is true when condition1 is true? Maybe some other reasonable equivalent snippet could be concocted that's easier to discover, and make the language hint in that direction. I feel like NaNs are a step forward, but better can be done. They allow error detection, but it's still merely runtime error detection, and worse yet, it's /non-local/ error detection. NaNs can spread from function to function and end up in completely different parts of a program than the place they originated. This causes debugging hell, just like null values. It makes me think that non-nan-able floating point types would be very useful, at least as function arguments, so that calling code doesn't have to introduce extra checks for NaNs that are either lost cycles or forgotten entirely and bug-ridden. I really wish we had a way of catching NaNs in the function or line where they happen, and not in completely distant parts of the code.
Aug 19 2012
On 8/19/2012 1:43 PM, Chad J wrote:So instead of writing float f; if (condition1) f = 7; ... code ... if (condition2) ++f; is there any way we can make it easier to write void someCode() { ... code ... } float f; if ( condition ) { f = 7; someCode(); ++f; } else someCode(); assuming that condition2 is true when condition1 is true?Yes, you can do that.I feel like NaNs are a step forward, but better can be done. They allow error detection, but it's still merely runtime error detection, and worse yet, it's /non-local/ error detection. NaNs can spread from function to function and end up in completely different parts of a program than the place they originated. This causes debugging hell, just like null values.I'm sorry, it's not debugging hell. I've done an awful lot of "figure out where this null came from" and it's a bit tedious, but not hell. You go step by step, such as "it's null in this function, so put an assert on the callers of the function", rinse, repeat. Yes, I also know this is more of a problem if you've got a program that's not so easy to rerun.It makes me think that non-nan-able floating point types would be very useful, at least as function arguments, so that calling code doesn't have to introduce extra checks for NaNs that are either lost cycles or forgotten entirely and bug-ridden.You can use signalling NaNs, if you like.I really wish we had a way of catching NaNs in the function or line where they happen, and not in completely distant parts of the code.Nobody has even mentioned this until I brought it up, so I have a hard time believing the current state of affairs is a terrible problem that requires a major redesign to fix. I know that nobody wants to see NaNs in their results, but be assured that that is far, far better than corrupted results that are off in subtle ways. NaNs are also one hell of a lot easier to track backwards than the other.
Aug 19 2012
On 08/19/2012 06:16 PM, Walter Bright wrote:On 8/19/2012 1:43 PM, Chad J wrote:Most of the programs I've worked on, be it hobby games or business apps for pay, have been interactive stuff. Rerunning sucks. Debuggers also interact very poorly with these things, or just plain have crappy interfaces that make using them a legitimate pain. My productivity is greatly improved by NOT having to do tedious busywork. This is why I have a very low tolerance for non-local bugs and a lack of good stacktrace info when crashing. I'd feel /a lot/ better if corrupt data like NaNs or nulls would create some kind of a crash or compiler error /before/ leaving the function that created them. IMO, this would be a huge step forward for programmer productivity. No longer does every nan/null take like 15-30 minutes to debug, it takes 1 minute instead.So instead of writing float f; if (condition1) f = 7; ... code ... if (condition2) ++f; is there any way we can make it easier to write void someCode() { ... code ... } float f; if ( condition ) { f = 7; someCode(); ++f; } else someCode(); assuming that condition2 is true when condition1 is true?Yes, you can do that.I feel like NaNs are a step forward, but better can be done. They allow error detection, but it's still merely runtime error detection, and worse yet, it's /non-local/ error detection. NaNs can spread from function to function and end up in completely different parts of a program than the place they originated. This causes debugging hell, just like null values.I'm sorry, it's not debugging hell. I've done an awful lot of "figure out where this null came from" and it's a bit tedious, but not hell. You go step by step, such as "it's null in this function, so put an assert on the callers of the function", rinse, repeat. Yes, I also know this is more of a problem if you've got a program that's not so easy to rerun.How? I remember reading a lot of material on NaNs in D, but I don't recall these.It makes me think that non-nan-able floating point types would be very useful, at least as function arguments, so that calling code doesn't have to introduce extra checks for NaNs that are either lost cycles or forgotten entirely and bug-ridden.You can use signalling NaNs, if you like.I doubt that preventing non-local bug propagation would require any kind of major redesign at this point. D seems very close already. Some kind of convenient notation for optional non-nullable (and maybe non-nan-able?) types combined with strictly simple branching initializations and some kind of easy-to-use sentinel values would probably go a long way. There seems to be a push to try and get this functionality from user-defined types. I am skeptical that it will ever work for these things because something like NotNull!MyType foo( NotNull!MyType a, NotNan!float b ) { ... } is going to be very daunting to write and read compared to something like MyType foo( MyType a, float b ) which is just a notation I've seen in previous posts. Initialization becomes a huge pain for the user-defined types too. Not only are proxy types like "NotNull!X" far more difficult to write in D than I would have expected, but things like non-null types and possibly non-nan types would be so common that things will probably look very nasty if people start using proxy types for this. I'm willing to wait and see if these proxy types can be made though, and if they get used a lot. I just hope their clumsiness doesn't inhibit their use. I understand it's easier to add things in demand than it is to remove things that are used infrequently.I really wish we had a way of catching NaNs in the function or line where they happen, and not in completely distant parts of the code.Nobody has even mentioned this until I brought it up, so I have a hard time believing the current state of affairs is a terrible problem that requires a major redesign to fix.I know that nobody wants to see NaNs in their results, but be assured that that is far, far better than corrupted results that are off in subtle ways. NaNs are also one hell of a lot easier to track backwards than the other.I agree that NaNs are really cool. They are definitely much better than "f=0;". Thank you for doing this.
Aug 19 2012
On 8/19/2012 6:33 PM, Chad J wrote:How? I remember reading a lot of material on NaNs in D, but I don't recall these.Set the control word for the x87 to turn it on. Probably have to do a little inline assembly.
Aug 19 2012
On 8/20/12, Walter Bright <newshound2 digitalmars.com> wrote:On 8/19/2012 6:33 PM, Chad J wrote:I thought you could do by setting FloatingPointControl in std.math.How? I remember reading a lot of material on NaNs in D, but I don't recall these.Set the control word for the x87 to turn it on. Probably have to do a little inline assembly.
Aug 20 2012
On 08/20/2012 11:09 AM, Andrej Mitrovic wrote:On 8/20/12, Walter Bright<newshound2 digitalmars.com> wrote:That looks much more convenient and clean. Gotta make the right thing easy to do, right? <g> How thread-local is it?On 8/19/2012 6:33 PM, Chad J wrote:I thought you could do by setting FloatingPointControl in std.math.How? I remember reading a lot of material on NaNs in D, but I don't recall these.Set the control word for the x87 to turn it on. Probably have to do a little inline assembly.
Aug 21 2012
On Tuesday, 21 August 2012 at 12:25:45 UTC, Chad J wrote:On 08/20/2012 11:09 AM, Andrej Mitrovic wrote:Except that it doesn't seem to work as expected (maybe an old compiler's bug..) RenoXOn 8/20/12, Walter Bright<newshound2 digitalmars.com> wrote:That looks much more convenient and clean. Gotta make the right thing easy to do, right? <g>On 8/19/2012 6:33 PM, Chad J wrote:I thought you could do by setting FloatingPointControl in std.math.How? I remember reading a lot of material on NaNs in D, but I don't recall these.Set the control word for the x87 to turn it on. Probably have to do a little inline assembly.How thread-local is it?
Aug 21 2012
On 21/08/12 16:14, renoX wrote:On Tuesday, 21 August 2012 at 12:25:45 UTC, Chad J wrote:Yeah, there's a bug in the code generation, at the moment for 80-bit reals it works on AMD but not Intel processors (!)On 08/20/2012 11:09 AM, Andrej Mitrovic wrote:Except that it doesn't seem to work as expected (maybe an old compiler's bug..)On 8/20/12, Walter Bright<newshound2 digitalmars.com> wrote:That looks much more convenient and clean. Gotta make the right thing easy to do, right? <g>On 8/19/2012 6:33 PM, Chad J wrote:I thought you could do by setting FloatingPointControl in std.math.How? I remember reading a lot of material on NaNs in D, but I don't recall these.Set the control word for the x87 to turn it on. Probably have to do a little inline assembly.
Aug 21 2012
Any chance that math.isNaN() will work at compile-time in the future? http://d.puremagic.com/issues/show_bug.cgi?id=8562 I haven't had the chance to study the source since last night, but is it not possible to check to see if something is a nan without doing a cast? On Fri, Aug 17, 2012 at 7:03 PM, Walter Bright <newshound2 digitalmars.com>wrote:Our discussion on this in the last few days inspired me to write a blog post about it: http://www.reddit.com/r/**programming/comments/yehz4/** nans_just_dont_get_no_respect/<http://www.reddit.com/r/programming/comments/yehz4/nans_just_dont_get_no_respect/> http://www.drdobbs.com/cpp/**nans-just-dont-get-no-respect/**240005723<http://www.drdobbs.com/cpp/nans-just-dont-get-no-respect/240005723>
Aug 20 2012