Disallow (dis)equality with FP.nan/FP.init literals
so
so at so.so
Wed Apr 18 18:36:10 PDT 2012
On Thursday, 19 April 2012 at 01:28:51 UTC, so wrote:
> On Thursday, 19 April 2012 at 00:50:09 UTC, bearophile wrote:
>> This is an open enhancement request that I'll probably add to
>> Bugzilla.
>> The direct cause of it is a recent discussion in D.learn, but
>> I and other people are aware of this problem for a lot of time.
>>
>>
>> Since a lot of time D statically refuses the use of
>> "classReference == null":
>>
>> // Program #1
>> class Foo {}
>> void main() {
>> Foo f;
>> assert(f == null);
>> assert(f != null);
>> }
>>
>>
>> test.d(4): Error: use 'is' instead of '==' when comparing with
>> null
>> test.d(5): Error: use '!is' instead of '!=' when comparing
>> with null
>>
>>
>>
>> A not expert D programmer sometimes compares a double with
>> double.nan in a wrong way:
>>
>> http://forum.dlang.org/thread/mailman.1845.1334694574.4860.digitalmars-d-learn@puremagic.com#post-jmlhfr:2428cv:241:40digitalmars.com
>>
>> because someDouble == double.nan is always false:
>>
>>
>> // Program #2
>> import std.math: isNaN;
>> void main() {
>> double x = double.init;
>> assert(x != double.nan);
>> assert(x != double.init);
>> assert(isNaN(x));
>> assert(x is double.init);
>> assert(x !is double.nan);
>>
>> double y = double.nan;
>> assert(y != double.nan);
>> assert(y != double.init);
>> assert(isNaN(y));
>> assert(y !is double.init);
>> assert(y is double.nan);
>> }
>>
>>
>>
>> I think there are three common wrong usage patterns of NaNs
>> testing:
>> 1) Test that x is equal to/different from nan using
>> x==FP.nan/x!=FP.nan
>> 2) Test that x is equal to/different from all NaNs using
>> x==FP.nan/x!=FP.nan
>> 3) Test that x is equal to/different from FP.init using
>> x==FP.init/x!=FP.init
>>
>> The case 3 is a bit less important because the programmer
>> already knows something about FP init, but it's wrong still.
>>
>> There are other wrong usages of NaNs but they are by more
>> expert programmers, to I don't want to catch them (example:
>> using "is" to test if x is equal to/different from all NaNs is
>> a bug, because there are more than one NaN. But if the
>> programmer uses "is" I assume he/she/shi knows enough about
>> NaNs, so this is not flagged by the compiler).
>>
>> Currently this program compiles with no errors:
>>
>>
>> // Program #3
>> void main() {
>> float x1 = float.nan;
>> assert(x1 == float.nan);
>> float x2 = 0.0;
>> assert(x2 != float.nan);
>> float x3 = float.init;
>> assert(x3 == float.init);
>> float x4 = 0.0;
>> assert(x4 != float.init);
>>
>> double x5 = double.nan;
>> assert(x5 == double.nan);
>> double x6 = 0.0;
>> assert(x6 != double.nan);
>> double x7 = double.init;
>> assert(x7 == double.init);
>> double x8 = 0.0;
>> assert(x8 != double.init);
>>
>> real x9 = real.nan;
>> assert(x9 == real.nan);
>> real x10 = 0.0;
>> assert(x10 != real.nan);
>> real x11 = real.init;
>> assert(x11 == real.init);
>> real x12 = 0.0;
>> assert(x12 != real.init);
>>
>> enum double myNaN = double.nan;
>> assert(myNaN == double.nan);
>> }
>>
>>
>>
>> So I propose to statically disallow comparisons of Program #3,
>> so it generates errors similar to:
>>
>> test.d(4): Error: comparison is always false. Use
>> 'std.math.isNaN' to test for every kind of NaN or 'is
>> float.nan' for this specific NaN
>> test.d(6): Error: comparison is always true. Use
>> '!std.math.isNaN' to test for every kind of NaN or '!is
>> float.nan' for this specific NaN
>> test.d(8): Error: comparison is always false. Use
>> 'std.math.isNaN' to test for every kind of NaN or 'is
>> float.init' for this specicif NaN
>> ...
>>
>>
>> Opinions, improvements, votes or critics are welcome.
>>
>> Bye,
>> bearophile
>
> Good idea.
> But nothing beats this:
>
> int main() {
> double q;
> q = 3.0/7.0;
> if (q == 3.0/7.0) printf("Equal\n");
> else printf("Not Equal\n");
> return 0;
> }
>
> http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
> Should we disable implicit conversion "at" comparison as well?
s/double/float/
"double" version also problematic but for another case.
More information about the Digitalmars-d
mailing list