Please enable Javascript to view the contents

[Rust Std Trait] (Partial)Ord/Eq 初见

 ·  ☕ 2 分钟

前言

    由于需要考虑全序关系(例如 Rust 浮点数中的 NaN),Rust 中有两套 trait 分别定义满足“全序”关系的 Ord/Eq 只能构成“偏序”关系的 PartialOrd/PartialEq。本文致力于用最短的篇幅覆盖标准库中Ord,Eq,PartialOrd,PartialEq的主要知识点。

Eq/PartialEq

    Eq 和 PartialEq 在概念上的区别主要是否满足 a == a,乍看之下是句废话。实则不然,例如 a = NaN 就是特例。而在 trait 的定义上 Eq 是基于 PartialEq 的,Eq 自己更多是起修饰作用,在#[derive]中,PartialEq 在类型字段全部相等时为 true反之false,而 Eq 只是约束类型全字段也满足 Eq。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
extern crate hello_rust;
#[derive(Debug, Eq)]
struct MyItem {
    id: i32,
    //... other Eq fields
}

impl PartialEq for MyItem {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id
    }
}

fn main() {
    let item1 = MyItem { id: 1 };
    let item2 = MyItem { id: 1 };
    assert_eq!(item1, item2);
}

    不难看出如果我们想用这套 trait,PartialEq 需要无脑怼上。需不需要 Eq 可以再考虑。

Ord/PartialOrd

    和前文一样,做这种区分就是因为一些特殊值例如 NaN < 0 == false 并且 NaN >= 0 == false。而在 trait 定义上 PartialOrd 基于 PartialEq 而 Ord 是 Eq + PartialOrd。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
use std::cmp::Ordering;

#[derive(Eq)]
struct Person {
    id: u32,
    name: String,
    height: u32,
}

impl PartialOrd for Person {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for Person {
    fn cmp(&self, other: &Self) -> Ordering {
        self.height.cmp(&other.height)
    }
}

impl PartialEq for Person {
    fn eq(&self, other: &Self) -> bool {
        self.height == other.height
    }
}

总结

    虽然上例演示使用了这套 trait,不过还是要说除 ==!= 以外的其他运算符的语义都比较固定,适用范围有限,避免滥用。

分享

saberuster
作者
saberuster
一个喜欢编程和折腾的追风少年