我有一个新类型,我想实现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)
}
}
当我尝试比较我的类型的两个变量时,会出现错误:
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
--> src/main.rs:5:6
|
5 | impl Ord for MyType {
| ^^^ the trait `std::cmp::Eq` is not implemented for `MyType`
当我实现PartialEq
,Eq
和PartialOrd
(gt()
,lt()
,Eq()
,ge()
,le()
)时,一切都很好,但如果我提供cmp
,我们可以推断出lt()
和Eq()
之类的函数!这是多余的!我不喜欢这个!
当查看文档时,我在Ord
的定义中看到了这一点:
pub trait Ord: Eq + PartialOrd<Self>
这看起来像是从Eq
和PartialOrd
继承的特征。为什么trait不能使用cmp
函数为继承的trait提供所需方法的默认实现?我不知道遗传特性是如何起作用的,搜索也没有什么用处,但我认为这应该是可能的。
这是如何在铁锈中完成的?我希望不是这样。。。
请将此视为原始答案的补充,适合您的具体情况。这个答案涉及你问题的第二部分。
考虑这个结构:
struct Person {
id: u32,
name: String,
height: u32,
}
PartialEq特性,来自文档
Trait for equality comparisons which are partial equivalence
relations. This trait allows for partial equality, for types that do not
have a full equivalence relation. For example, in floating point numbers
NaN != NaN, so floating point types implement PartialEq but not Eq.
Formally, the equality must be (for all a, b and c):
symmetric: a == b implies b == a; and
transitive: a == b and b == c implies a == c.
因此,如果您想表达类型的值相等意味着什么,您必须实现ParatalEq
特性。实现它允许我们写x==y
和x!=y
为我们的类型。
impl PartialEq for Person {
fn eq(&self, other: &Person) -> bool {
self.height == other.height
}
}
请注意,我们只是根据高度来确定Person
struct的相等性。如果要比较每个结构字段,也可以实现此eq
方法:
fn eq(&self, other: &Person) -> bool {
self.id == other.id && self.name == other.name && self.height == other.height
}
但是,如果您想要的是这种行为,那么简单地添加#[派生(部分Eq)]
会更容易。
Eq特征,来自文档
Trait for equality comparisons which are equivalence relations.
This means, that in addition to a == b and a != b being strict inverses,
the equality must be (for all a, b and c):
reflexive: a == a;
symmetric: a == b implies b == a; and
transitive: a == b and b == c implies a == c.
This property cannot be checked by the compiler, and therefore Eq implies
PartialEq, and has no extra methods.
Derivable
This trait can be used with #[derive]. When derived, because Eq has no extra methods,
it is only informing the compiler that this is an equivalence relation rather than a
partial equivalence relation. Note that the derive strategy requires all
fields are Eq, which isn't always desired.
PartialEq用于不一定是自反的关系(也就是说,可以有这样的x,x!=x),Eq是一个标记特征,表示关系也是自反的(现在它是一个适当的等价关系)。
您还可以使用空impl块手动实现Eq
trait
impl Eq for Person {}
但是,同样,将Eq
添加到#[派生(Eq)]
列表更容易。
使用运算符
在实现
PartialOrd
之前,必须先实现PartialEq
。
impl PartialOrd for Person {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
排序
是具有以下值的枚举:
pub enum Ordering {
Less,
Equal,
Greater,
}
partial\u cmp
返回一个选项,而不是一个
排序
,因为有些类型的值不能总是进行比较,例如浮点数NaN
s不是可表示的数字;表达式,如3.0
事实上,
partial_cmp
返回一个选项
在实现
Ord
之前,必须先实现PartialOrd
、Eq
和PartialEq
。
对于我们的
Person
struct,我们可以再次委托给我们的一个成员变量:
impl Ord for Person {
fn cmp(&self, other: &Person) -> Ordering {
self.height.cmp(&other.height)
}
}
对于初学者,您只能实现PartialOrd::partial_cmp
,因为lt
、le
、gt
、和ge
都有默认实现。此外,如果您实现Ord
,您可以像往常一样简单地实现cmp
,而partial\u cmp
只会变成Some(self.cmp(other))
。
然而,如果您只想委托给某个字段的平等和有序概念,那么它要好得多,也更容易推导:
#[derive(PartialOrd, Ord, PartialEq, Eq)]
struct MyType(isize);
对于您的具体情况,我将使用#[派生]
:
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
struct MyType(isize);
fn main() {
let a = MyType(5);
let b = MyType(6);
println!("{:?}", a.cmp(&b))
}
如果您需要对您的Ord
实现进行特殊处理,您仍然需要写出代码,没有什么可以帮我们解决这个问题!如果这样做有意义的话,您仍然可以派生其他特性的实现。
你问题的另一部分模棱两可,因此我将从两个方面回答:
为什么使用PartialOrd
的任何东西都不能自动提供Ord
?
让我们看看PartialOrd
和Ord
的文档。
PartialOrd
说:“比较必须满足反对称性和及物性”,而Ord
说:“形成总顺序的类型”。这些都是数学术语,我不会像维基百科那样描述它们。
但是,我们可以使用浮点数作为示例。浮点数有一个特殊的值,称为NaN
。与这个值进行比较是很棘手的。例如,所有的1.0
我们不能用
PartialOrd
来定义Ord
,因为我们对底层类型没有适当的保证。这是Rust的类型系统,可以避免我们犯错误!
为什么使用
Ord
的任何东西都不能自动提供PartialOrd
?
这里的问题是
PartialOrd
类型比Ord
类型多。如果我们要求所有内容都是Ord
,那么我们就不能进行任何浮点比较,因为它们没有总顺序,否则我们就不得不放弃总顺序,失去它提供的安全性。
但是,有一些想法可以自动为
派生
执行此操作。拟议的RFC 2385将允许将上述代码缩减为:
#[derive(Debug, Copy, Eq, Ord)]
struct MyType(isize);
当我实现
PartialOrd
(gt()
,lt()
,eq()
,ge()
,le()
)
请注意,
PartialOrd
有默认实现,您只需要实现partial\u cmp
。其他的是为了便于使用或可能是性能原因。
在的留档中,它说 实现必须与PartialOrd实现一致[…] 这当然是有道理的,并且可以很容易地归档,如下面的示例所示: 我想知道,为什么他们会把这个负担/风险留给我们用户,而不是用毯子 我在操场上测试了循环依赖和其他东西的问题,但这和我预期的一样有效。互联网也没有产生任何结果。 我能想到的另一个原因是宏现在是如何工作的。人们可能必须将每个替换为(或者将(PartialOrd)的宏变得更智能-我
我见过一个类似的问题,但是没有人告诉我如何为结构实现Ord。例如,以下内容: 这给了我一个错误: 我该怎么解决这个问题?我尝试将实现更改为: 并添加适当的和函数,但这给了我一个错误,即这两种方法都不是的成员。
我正在尝试将与自定义结构一起使用。为此,我必须让我的结构实现trait,但我需要的是相同结构的2个s,但顺序不同。 有没有办法定义2 Ord实现 我想我可以定义两个不同的包装结构,它们保留了对原始自定义结构的引用,并为每一个定义了一个的实现,但是必须构建大量这样的包装结构的实例似乎是相当浪费的。 在Pyhton/Java我会提供一个排序函数/比较器,但似乎没有这样的设施。在Scala中,我可以定义
本文向大家介绍awk中实现ord函数功能,包括了awk中实现ord函数功能的使用技巧和注意事项,需要的朋友参考一下 在awk中并未直接提供ord函数,所以在将某个字符转换为码时,需要自己来实现 这里主要是构造了ord为key,val的数据结构,key为char字符,val对应的ascii码 附:awk得到字母的ASC值实现
描述 (Description) 此函数返回EXPR指定的字符的ASCII数值,如果省略则返回$ _。 例如,ord('A')返回值65。 语法 (Syntax) 以下是此函数的简单语法 - ord EXPR ord 返回值 (Return Value) 此函数返回Integer。 例子 (Example) 以下是显示其基本用法的示例代码 - #!/usr/bin/perl -w print("
我想要一个方法,用于、和,因此我创建了一个trait: 我得到一个错误: 根据Rust标准库文档,未实现。为什么存在冲突的实现?