NaNs Just Don't Get No Respect
Davidson Corry
davidsoncorry at comcast.net
Mon Aug 20 17:45:05 PDT 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...)
>> Yes, it would be great if the D compiler (or a C++11 compiler, or C#
>> 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."
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'!
>> 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.
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.
>> ...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".)
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
More information about the Digitalmars-d-announce
mailing list