Despite I am using Rust since months, I am not yet afraid of asking simple questions I don't understand the design of PartialEq/Eq/PartialOrd/Ord. Currently I am seeing an asymmetry.
Currently the four traits are:
trait PartialEq<Rhs = Self> where Rhs: ?Sized {
fn eq(&self, other: &Rhs) -> bool;
//...
}
trait Eq: PartialEq<Self> {}
trait PartialOrd<Rhs = Self>: PartialEq<Rhs> where Rhs: ?Sized {
fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
//...
}
trait Ord: Eq + PartialOrd<Self> {
fn cmp(&self, other: &Self) -> Ordering;
}
Why aren't they designed like this:
trait PartialEq<Rhs = Self> where Rhs: ?Sized {
fn partial_eq(&self, other: &Rhs) -> Option<bool>;
//...
}
trait Eq: PartialEq<Self> {
eq(&self, other: &Rhs) -> bool;
}
trait PartialOrd<Rhs = Self>: PartialEq<Rhs> where Rhs: ?Sized {
fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
//...
}
trait Ord: Eq + PartialOrd<Self> {
fn cmp(&self, other: &Self) -> Ordering;
}
Or like this?
trait PartialEq<Rhs = Self> where Rhs: ?Sized {
eq(&self, other: &Rhs) -> bool;
//...
}
trait Eq: PartialEq<Self> {}
trait PartialOrd<Rhs = Self>: PartialEq<Rhs> where Rhs: ?Sized {
fn partial_cmp(&self, other: &Rhs) -> Ordering;
//...
}
trait Ord: Eq + PartialOrd<Self> {}
And related to that, here I don't understand what function "a < b" is actually calling:
fn test<T: PartialOrd>(a: T, b: T) -> bool {
if a < b { true } else { false }
}
fn main() {
use std::f64::NAN;
println!("{}", test(NAN, NAN)); // Output: false
}
partial_cmp() should return an Option. If T is PartialOrd then I think performing "a < b" should be disallowed, and you should just call partial_cmp() and handle the Option<>. Unless Ord is defined like:
trait Ord: Eq + PartialOrd<Self> {}
Just like in the "==" case.
(Lot of Rust design is very symmetric and clean, so unless I am missing some things I guess the asymmetry/kludge I am perceiving here was introduced for strong practicality reasons).