Two kinds of ordering
I feel there are two kinds of "ordering". One is "semantic" ordering, which arises when users (especially the humanity) interpret the value. And the other is... let's call it "systematic" ordering, which is required to put into or retrieve from containers, but not necessarily brings natural interpretation.
I think that the meaning and use of Ord
is ambiguous.
Does (or should) developers implement it as "semantic" ordering, or "systematic" ordering?
And, does users always consider it as "semantic" ordering, or sometimes they expect Ord
to be "systematic" ordering?
Should it implement Eq
and Ord
? If so, what they actually mean?
For example, consider defining a value type for generic data serialization format.
#[derive(Debug, Clone, Copy)]
enum Value {
Null,
Boolean(bool),
Integer(bool, u64),
Float(f64),
String(String),
}
Question: Is it natural to implement PartialEq
, Eq
, PartialOrd
, and Ord
?
As a human:
- They can implement
PartialEq
andEq
.-
NaN
s should be compared bitwise (as they have additional info). - Depending on specification or use cases, we want
Integer(true, 42)
andFloat(42.0)
to be equal, or not equal. Anyway some consistent ordering can be defined.
-
- They shouldn't implement
PartialOrd
andOrd
.- Thinking about the ordering among
null
,true
,"foo"
, and3.14
would be nonsense. - Should
true
be "less than""foo"
, or not? In both case, why?
- Thinking about the ordering among
From this point of view, I consider [Partial]Eq
and [Partial]Ord
as "semantic" ordering.
But as a developer:
- They can have total order (not necessarily natural nor meaningful for human).
- It is quite natural to use the value as keys of
BTreeSet
,BTreeMap
, or some other key-value containers.- Ordering would be non-intuitive for human, but it does not matter. Consistency is only we need.
- Consider you want to normalize the set of the value. You would use
BTreeSet<Value>
, or useVec<Value>
and.sort()
it.- It is quite natural to make
Vec<Value>
sortable, i.e. to giveValue
total order.
- It is quite natural to make
- It is quite natural to use the value as keys of
From this point of view, I see [Partial]Eq
and [Partial]Ord
are required by the containers as "systematic" ordering.
Ambiguity from language and std design?
I've faced this problem several times, and made a decision without 100% confidence every time. I think this relatively simple problem does not have perfect answer for now, and it is because of the language (and/or the standard library) design.
Since Rust 1.62.0 (released today), f64::total_cmp
is provided. I feel that this is "systematic" ordering, and that containers requiring Ord
should essentially require this kind of ordering, rather than "semantic" ordering provided by traditional PartialOrd
and Ord
.
Opinions?
So, I'd like to hear your opinions:
- Are there really "semantic" ordering and "systematic" ordering? Do you need more variantions, or are they essentially equivalent and merged to single ordering?
- If it is better to have them distinct traits, is it possible to change Rust and the standard libraries to use them with or without breaking changes? If possible, how?
- Or, is this mitigated by the third-party libraries outside the std?
- I'm not sure "semantic" and "systematic" is the best words... Any other better words?