Movement against float.init being nan

Steven Schveighoffer schveiguy at gmail.com
Mon Aug 22 11:41:33 UTC 2022


On 8/21/22 12:51 PM, Walter Bright wrote:
> Consider the following pattern, which doesn't appear frequently, but 
> frequently enough:
> 
>      double x;
>      if (condition) {
>          x = 5;
>          ...
>      }
>      ...               // (1)
>      if (condition) {
>         foo(x);
>      }
> 
> Imagine there's a lot more code omitted which obscures the pattern. This 
> code is correct.
> 
> Now, maintainer adds `bar(x)` at (1).
> 
> The scenarios:
> 
> 1. x is default initialized to NaN. bar(x) produces a NaN result on 
> everything dependent on x. User knows there's a problem.

How? No exception is thrown, no error occurs. Unless bar somehow checks 
for NaN, nothing happens. Just like it is for 0. Perhaps it saves the 
result of bar computation to something for later use. Then that now gets 
propagated to some other use, and then, deep somewhere, NaN appears in 
something that appears completely unrelated to bar or x. How do you 
trace it back?

> 2. x is default initialized to 0. bar(0) may exhibit problems, but these 
> problems won't necessarily be noticed.

Just like NaN.

> 3. compiler complains that `double x;` needs an initializer. To shut up 
> the compiler, the user initializes it to 0, without putting much thought 
> into it. bar(0) may exhibit problems, but these won't necessarily be 
> noticed.
> 
> 4. compiler complains that `double x;` needs an initializer. Coder just 
> schlepps in a 0. Yes, this happens. Maintainer wastes time wondering why 
> x is initialized to 0, as that may be a nonsense value for x. Maintainer 
> wonders if this unused initialization has a purpose, maybe it is the 
> result of a bad refactoring? Wastes more time investigating it.

Huh? Why are there 2 identical situations here?

I'll also point out that not initializing an integer is sometimes 
intentionally done (because it's equivalent to initializing to 0). If I 
see someone didn't assign a value to an int, I don't question if it was 
an accident, I expect that they meant it.

Also, you forgot:

5. Maintainer expected x to default to 0 (because that's what most types 
do), and expected bar to be called with 0 or 5. Now, since bar saved the 
result of it's calculation elsewhere, and then far away from this code, 
the result is used in some computation that finally makes its way to 
output in some fashion (and possibly not a specific printing of the 
value), now there's a puzzle to solve, and no way to know it can be 
traced back to x without hours/days of searching.

> D chose option 1.

And there's probably no way that it changes. But in my mind the correct 
answer is to intialize to 0.

-Steve


More information about the Digitalmars-d mailing list