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:
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).

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.

Reply via email to