On 07/08/15 20:22, Chris Angelico wrote:
The intention of nan!=nan is that any two calculations that yield NaN are guaranteed to compare unequal, even if they happen to produce the same payload. (As IEEE floating point formats have finite storage, yet there are infinite non-numbers, collisions can occur.) Container handling in Python presumes upon having another reference to the exact same NaN object, even if two of them happen to have the same bit-pattern; Pike can approximate to this by requiring that the payloads be identical, which gives roughly one chance in 2**53 that arbitrarily-generated NaNs will errantly match in a container. Allowing _any_ NaN to match _any_ other NaN seems to be an unnecessary violation of IEEE principles, while not giving any benefit in terms of container handling. Example:
mapping m=([]); float f1=get_a_number(); float f2=get_a_number(); m[f1] = "f1"; m[f2] = "f2"; foreach (indices(m), float key) write("m[%O] = %O\n", key, m[key]); write("Expecting size %d, actually %d\n", 1 + (f1!=f2), sizeof(m));
In the absence of NaNs, this should always produce sane results. Either the two numbers are equal and one overwrote the other, or they're not. If both are NaN and their payloads happen to collide, then it'll produce odd results (unequal but overwritten). But if they're both NaN and their payloads do not collide, then everything should happen sanely - you look up the two NaNs and get back "f1" and "f2" from the mapping, which has a length of 2, which is expected (as the two are unequal). Yes, the payload itself may not be visible from Pike, but you can pull a key out of the mapping and then use it to look the value up (which guarantees that the payload hasn't changed, since the value hasn't changed in any way), and payload checking gives at least a chance that NaNs will behave properly. Of course, it's entirely possible that the payloads aren't random, so they'll collide frequently; but that probably depends on the specific hardware, and unless Pike specifically invents a concept of NaN identity, it's a limitation that can't be broken.
If we would define NaN floats to compare equal, all the inconsistencies would go away. So your above example would work just fine with NaNs. However, it would be quite a radical choice, I will not lobby for it any further ;)
On the other hand, we do not have the choice to implement an identity similar to what python has. So we _do_ have to invent a concept of NaN identity based on the value of the payload. We agree that it has to be restricted to containers. I personally don't like the idea of having something that breaks sometimes. To me it would seem that it makes NaN floats inside of container no more useful than they currently are. Of course, other people might have different priorities. I am then only left with one option, namely having the key comparison treat all NaNs equal.
As a side note: ECMAScript 6 Map and Set types seems to treat key equality roughly as I propose.
Arne