Movement against float.init being nan
Walter Bright
newshound2 at digitalmars.com
Sat Aug 20 05:18:20 UTC 2022
On 8/19/2022 8:12 PM, Steven Schveighoffer wrote:
> On 8/19/22 9:01 PM, Walter Bright wrote:
>> On 8/19/2022 12:09 PM, Steven Schveighoffer wrote:
>>> But it defaults to a completely useless value (NaN).
>>
>> It is not useless. NaN's have many uses, one of which is to not have silent
>> bugs where you forgot to initialize a double.
>
> Knowing that somewhere, in some code, someone didn't initialize a double, is not
> useful. And that's if you notice it.
>
> In fact, NaN creates silent bugs.
I don't see how. Any operation with a NaN produces a NaN result. If you've got a
NaN result, it can be traced back to its source. This is hard with 0 initialization.
>> It's fewer hours then tracking down why it is 0 instead of 6, because 0
>> doesn't leave a trail.
>
> That's not what happens. You see, when you do `DrawSquare(x, y)`, nothing
> happens. No exception thrown, no "Bad Square" drawn to the screen, it's like
> your function didn't get called. You start questioning just about every other
> aspect of your code (Am I calling the function? Is the library calling my
> function? Is there a bug in the library?). You don't get any indication that x
> is NaN. Whereas, if it's zero, and that's *wrong*, you see a square in the wrong
> spot, and fix it.
I don't know why floating point for drawing coordinates? Besides, when I wonder
if a function is being called, I put a printf in it. Or set a breakpoint in the
debugger. This is routine debugging work. Then I'll look at the values of the
parameters. Again, routine. Back in the olden days, I'd have the embedded system
click the speaker to see if it entered a function :-)
> In other words, NaN is silent. You can't even `assert(x != double.init)`. You
> have to use an esoteric function `isNaN` for that.
It is not silent. Every single usage of NaN produces a NaN result. If printing a
NaN value, the result is "NaN".
> But all the code that *does* expect 0 to be the default would become useful. So
> there's upsides both ways -- the silent nature of NaN bugs goes away, and now
> your code doesn't have to always assign a value to a float buried in a struct.
struct S { float x = 0; }
> Why not just require initialization? I'm mostly curious, because I don't think
> it's possible to do now, but why didn't you do that originally?
Because I've seen what happens with that. The compiler complains about no
initializer, and the programmer just puts in "0" to shut up the compiler. He
does not make the effort to figure out what it should be initialized to. The
reviewer wastes time trying to figure why it is uselessly initialized to zero.
This is an especial problem when the initialized value is never used. The
reviewer is left wondering if it is a bug. D is designed this way so that
explicit initializations to a value are *intentional* rather than a side effect
of compiler error messages.
This is all part of D's design to encourage writing code that is easier to
debug, review and maintain. Even if it takes a little more writing up front.
More information about the Digitalmars-d
mailing list