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

Reply via email to