This is also why Rust has separate PartialEq and Eq traits - the latter is only available for types that don't have weird not-self-equal values like floating point NaNs or SQL NULLs. If you lie to Rust and create a wrapper type over f32 or f64 that has Eq, then you'd get unindexable NaN keys that just sit in your hashmap forever.
The real surprise to me is that Python can index NaN keys sometimes, at least by reference to the original NaN. I knew CPython does some Weird Shit with primitive values, so I assume it's because the hashmap is comparing by reference first and then by value.
> Last week in the Python Discord we had an unusual discussion about a Python oddity.
Oh, I missed it. But yes, this is more to do with NaN than Python.
> But, of course, you can't actually get to those values by their keys: ... That is, unless you stored the specific instance of nan as a variable:
Worth noting that sets work the same way here, although this was glossed over: you can store multiple NaNs in a set, but not the same NaN instance multiple times. Even though it isn't equal to itself, the insertion process (for both dicts and sets) will consider object identity before object equality:
>>> x = float('nan')
>>> {x for _ in range(10)}
{nan}
And, yes, the same is of course true of `collections.Counter`.
IEEE 754 prescripes, for better or worse, that any mathematical comparison operator (==, <, > ….) involving at least one NaN must always return false, including comparison against itself. This is annoying for something like dictionaries or hashtables. C# has a solution: if you call a.Equals(b) on two floats a and b, it will return true also if both are NaN. I think this is a cool solution: it keeps the meaning of math operators the same identical with other languages, but you still have sensible behavior for containers. I believe this behavior is copied from Java.
This got me curious, and yeah it turns out Elm's dictionary implementation uses values, not pointers when retrieving values.
elm repl
---- Elm 0.19.1 ----------------------------------------------------------------
Say :help for help and :exit to exit! More at <https://elm-lang.org/0.19.1/repl>
--------------------------------------------------------------------------------
> import Dict exposing (Dict)
> nan = 0/0
NaN : Float
> nan
NaN : Float
> nan == nan
False : Bool
> naan = 0/0
NaN : Float
> d = Dict.fromList [(nan, "a"), (naan, "b")]
Dict.fromList [(NaN,"a"),(NaN,"b")]
: Dict Float String
> Dict.toList d
[(NaN,"a"),(NaN,"b")]
: List ( Float, String )
> Dict.keys d
[NaN,NaN] : List Float
> Dict.get nan d
Nothing : Maybe String
> Dict.get naan d
Nothing : Maybe String
13 comments
[ 0.22 ms ] story [ 29.6 ms ] threadIt makes little sense that 1/0 is SIGFPE, but log(-5) is NaN in C.
And the same is true for higher level languages, and their error facilities.
What a mess.
*This is false, NaN is weird, though maybe it needs to be. It is nowhere written arithmetic on computers must be straightforward.
The real surprise to me is that Python can index NaN keys sometimes, at least by reference to the original NaN. I knew CPython does some Weird Shit with primitive values, so I assume it's because the hashmap is comparing by reference first and then by value.
[1] https://stackoverflow.com/questions/18291620/why-will-stdsor...
There are so many discussions about "X language is so weird about it handles numbers!" and it's just IEEE 754 floats.
Oh, I missed it. But yes, this is more to do with NaN than Python.
> But, of course, you can't actually get to those values by their keys: ... That is, unless you stored the specific instance of nan as a variable:
Worth noting that sets work the same way here, although this was glossed over: you can store multiple NaNs in a set, but not the same NaN instance multiple times. Even though it isn't equal to itself, the insertion process (for both dicts and sets) will consider object identity before object equality:
And, yes, the same is of course true of `collections.Counter`.https://archive.tinychan.net/read/prog/1176222557
PS: Wait for it ... Watman! =8-)