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.