Refuse a comparison against NaN rather than ordering it (#947) - #954
Merged
Conversation
Real's >, >=, < and <= ordered NaN above every number, so NaN > 1 was true and 1 < NaN was true as well -- EDecimal's total order showing through, and not what double does, where every comparison against NaN is false in both directions. The failure it caused is one-sided and it is the unsafe side: a guard written as `if (value > threshold)` treated an undefined value as exceeding the threshold. Not answering is a legitimate answer here and answering wrongly is not. CompareTo is deliberately left ordering NaN. Sorting needs a total order and Array.Sort may loop or throw without one, while an operator needs no such thing; "where does this sort" and "is this greater" are different questions and only the second has no answer for a value that is not a number. Both halves are now pinned by the test, because each reads as an inconsistency on its own and only makes sense beside the other. Suite 7263 passed, 0 failed -- nothing in the library relied on the old ordering. Recorded in BREAKING-CHANGES.md as silent.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #947.
Real's>,>=,<and<=orderedNaNabove every number:That is
EDecimal's total order showing through, and it is not whatdoubledoes, where every comparison againstNaNis false in both directions.The failure it caused is one-sided, and it is the unsafe side. A guard written as
if (value > threshold)treated an undefined value as exceeding the threshold. Of the two possible defaults that is the worse one, and the library's stated position is that answering wrongly is worse than not answering.CompareTois deliberately unchangedThis is the part worth reviewing, because it looks like an inconsistency and is not one.
Sorting requires a total order —
Array.Sortmay loop or throw without one — while an operator requires no such thing. "Where does this sort" and "is this greater" are different questions, and only the second has no answer for a value that is not a number. SoCompareTostill putsNaNabove every number, and a caller who was relying on the operators to sort should call it instead.Both halves are pinned by
RealComparisonTest, including a test that actually sorts an array containingNaN, because each half reads as a mistake on its own and only makes sense beside the other.Evidence
NaN's comparisons against itself (NaN >= NaNis now false), which is the row most likely to be got wrong from habitBREAKING-CHANGES.md, marked Silent: the call still succeeds and returns the opposite booleanWhat it does not do
CompareTo,Equals, or==.Entity's comparison operators, which build an inequality node rather than answering abool— a different thing entirely.NaNsorts anywhere.🤖 Generated with Claude Code