NaNs Just Don't Get No Respect

F i L witte2008 at gmail.com
Fri Aug 17 18:07:42 PDT 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
     }


More information about the Digitalmars-d-announce mailing list