虽然Rust实现的所有整数类型Ord都强调总排序,但浮点类型只能实现PartialOrd.这意味着可能存在无法比较的浮点值.这似乎很难消化,因为浮点数可以被认为是实数的近似值,恰好是一个完全有序的集合.即使增加正负无穷大也能保持实数的整数排序.为什么这个奇怪的选择在Rust?
此限制意味着通用排序/搜索算法只能假设数字的部分排序.IEEE 754标准似乎提供了总排序谓词.
NaN在通用代码中是如此多的问题吗?
我已经看到了一个与此类似的问题,但没有人告诉我如何实现Ord结构.例如,以下内容:
struct SomeNum {
name: String,
value: u32,
}
impl Ord for SomeNum {
fn cmp(&self, other:&Self) -> Ordering {
let size1 = self.value;
let size2 = other.value;
if size1 > size2 {
Ordering::Less
}
if size1 < size2 {
Ordering::Greater
}
Ordering::Equal
}
}
Run Code Online (Sandbox Code Playgroud)
这给了我错误:
error: the trait `core::cmp::Eq` is not implemented for the type `SomeNum` [E0277]
Run Code Online (Sandbox Code Playgroud)
我该如何解决这个问题?我尝试将实现更改为:
impl Ord for SomeNum where SomeNum: PartialOrd + PartialEq + Eq {...}
Run Code Online (Sandbox Code Playgroud)
并添加适当的partial_cmp和eq函数,但它给我的错误,这两个方法都不是成员Ord.
在的文档Ord中,它说
实现必须与 PartialOrd 实现一致 [...]
这当然是有道理的,并且可以轻松存档,如下面的示例所示:
impl PartialOrd for MyType {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道,为什么他们会把这种负担/风险留给我们用户而不是有一条毯子impl<T: Ord> PartialOrd for T { /* ... */ }。
我测试了循环依赖问题和游乐场中的东西,但这正如我所期望的那样。互联网也没有产生任何结果。
我能想到的另一个原因是derive宏现在的工作方式。人们可能必须将每个替换derive(PartialOrd, Ord)为 just derive(Ord)(或者使宏变得PartialOrd更智能 - 我不知道它是否可以变得那么智能)。
添加建议的总体实现将禁止自定义实现PartialOrd并消除一致性要求。当然,这对图书馆来说是一个重大改变。这是唯一的原因,还是我在这里遗漏了一些其他论点?
我有一个newtype,我想实现Ord:
use std::cmp::{Ord, Ordering};
struct MyType(isize);
impl Ord for MyType {
fn cmp(&self, &other: Self) -> Ordering {
let MyType(ref lhs) = *self;
let MyType(ref rhs) = *other;
lhs.cmp(rhs)
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试比较我的类型的两个变量时,我得到错误:
error[E0277]: the trait bound `MyType: std::cmp::PartialOrd` is not satisfied
--> src/main.rs:5:6
|
5 | impl Ord for MyType {
| ^^^ can't compare `MyType` with `MyType`
|
= help: the trait `std::cmp::PartialOrd` is not implemented for `MyType`
error[E0277]: the trait bound `MyType: std::cmp::Eq` is not satisfied …Run Code Online (Sandbox Code Playgroud)