This was rather surprising (from Clojure: The Essential Reference book)
(sort [3 2 Double/NaN 0])
;; => (0 2 3 ##NaN)
(sort [2 3 Double/NaN 0])
;; => (2 3 ##NaN 0)
NaN is wacky in general. :)
See
user=> (< 1.0 ##NaN)
false
user=> (> 1.0 ##NaN)
false
user=> (= 1.0 ##NaN)
false
user=> (== 1.0 ##NaN)
falseI guess I don't mind that the position of NaN in the "sorted" collection is unpredictable. But that it breaks ordering of another elements... that surprised me 😮
sort just completely breaks because ##NaN is both not smaller than and not bigger than any other number.
Different sort algorithms would produce different results based on how they attempt comparisons and partitioning, but they would all break with ##NaN in the mix, since sorting requires complete ordering (and ##NaN does not offer that).
just replace ##NaN with ##Banana in your mind and figure out what the behavior should be. because bananas are also not numbers
You could use sort-by and provide a key-fn that maps ##NaN to something comparable (mapping it to ##Inf would cause it to be sorted at the end, for example).
user=> (sort-by #(if (NaN? %) ##Inf %) [2 3 Double/NaN 0])
(0 2 3 ##NaN)
user=> (sort-by #(if (NaN? %) ##Inf %) [3 2 Double/NaN 0])
(0 2 3 ##NaN)
But of course at this point you're not even trying to sort bananas any more 🙂> because ##NaN is both not smaller than and not bigger than any other number.
And neither is it equal to itself. It exists to prevent us programmers from ever becoming too confident.
Java's TimSort reqiures collection elements to be comparable transitively. NaN breaks that requirement.
Technically NaN breaks even more basic reflexivity (a == a) requirement. Double.NaN == Double.NaN is false. Transitivity means (a == b) and (b == c) => (a == c) but of course it's broken too for NaNs. > Maybe-not interesting fact. Rust has this in type system and enforces it at compile time; floats implements PartialEq trait (for partial equality because of NaNs) while ints have Eq trait (total equality).