为什么`sort()`需要`T`是`Ord`?

Aur*_*ier 7 rust

https://doc.rust-lang.org/src/alloc/slice.rs.html#268-270

https://doc.rust-lang.org/src/core/cmp.rs.html#1034

pub fn sort(&mut self)
where
    T: Ord,
{
    merge_sort(self, |a, b| a.lt(b));
}

fn lt(&self, other: &Rhs) -> bool {
    matches!(self.partial_cmp(other), Some(Less))
}
Run Code Online (Sandbox Code Playgroud)

lt()merge_sort(). 如果partial_cmp()返回Nonelt()返回Less

所以,似乎PartialOrd已经足够了sort()

Zet*_*eta 13

既有历史原因,也有逻辑原因。

早在以前impl<T> [T]sort首先使用cmp()代替lt()。出于优化原因,这种情况在大约 5 年前发生了变化。那时,约束可以从 更改OrdPartialOrd。确实,它引发了另一场关于和 的讨论PartialOrdOrd

然而,也有一个合乎逻辑的原因:对于任意两个索引ij内的[0..values.len()]i <= j,您希望以下内容保存是否values已排序:

assert!(values[i] <= values[j]);
Run Code Online (Sandbox Code Playgroud)

请注意,我说的是任何索引,其中i <= j. 然而,通过PartialOrd,我们可以获得一些x与任何其他值都无法比较的值,例如f64::NAN。在这种情况下,完全不清楚x应该在哪里排序,因为any f64::NAN < y产量y < f64::NAN,并且您的期望被误导了,您的一天被毁了。为了真正对所有值进行排序,我们需要所有值都可以与整个域进行比较。但正是如此。false yOrd

现在,实现可以将所有不可比较的值放在集合的末尾,但这将是一个任意的决定,可能会产生令人惊讶的结果。sort但Rust 标准库并没有在 中使用一些看似随机的方法,sort_by而是让能够做出决定:

values.sort_by(|a, b| a.partial_cmp(b).unwrap());
Run Code Online (Sandbox Code Playgroud)

现在这是一个明确的选择。正如Python Zen所说:“显式优于隐式。”