[Rust笔记] 一文讲透Rust中的PartialEq和Eq

感谢chaseSpace的投稿,原文链接:https://github.com/chaseSpace/rust_practices/blob/main/blogs/about_eq_ord_trait.md

  • 前言

  • 1. 数学中的相等关系

    • 1.1 部分相等关系

    • 1.2 部分相等与全相等的关系

    • 1.3 小结

  • 2. 编程与数学的关系

  • 3. PartialEq

    • 3.1 trait定义

    • 3.2 对应操作符

    • 3.3 可派生

    • 3.4 手动实现PartialEq

    • 3.5 比较不同的类型

    • 3.6 Rust基本类型如何实现PartialEq

  • 4. Eq

    • 4.1 trait定义

    • 4.2 对应操作符

    • 4.3 可派生

    • 4.4 手动实现Eq

    • 4.5 比较不同的类型

    • 4.6 Rust基本类型如何实现Eq

  • 5. 对浮点数的测试

  • 6. PartialOrd和Ord

    • 6.1 与PartialEq和Eq的关系

    • 6.2 基本性质

    • 6.3 trait定义

    • 6.4 可派生

    • 6.5 手动实现PartialOrd和Ord

    • 6.6 比较不同的类型

    • 6.7 Rust基本类型如何实现PartialOrd和Ord

    • 6.8 为其他类型实现四大compare-trait

前言

本文将围绕对象:PartialEq和Eq,以及PartialOrd和Ord,即四个Rust中重点的Compare Trait进行讨论并解释其中的细节,内容涵盖理论以及代码实现。

在正式介绍PartialEq和Eq、以及PartialOrd和Ord之前,本文会首先介绍它们所遵循的数学理论,也就是相等关系。文章主要分三大部分,第一部分是第1节,讨论的是数学中的相等关系;第二部分是第2~5节,主要讨论PartialEq和Eq;第三部分是第6节,主要讨论PartialOrd和Ord。内容描述可能具有先后顺序,建议按章节顺序阅读。

声明

本文内容来自作者个人的学习成果总结及整理,可能会存在因个人水平导致的表述错误,欢迎并感谢读者指正!

  • 作者:Leigg

  • 首发地址:https://github.com/chaseSpace/rust_practices/blob/main/blogs/about_eq_ord_trait.md

  • CSDN:https://blog.csdn.net/sc_lilei/article/details/129322616

  • 发布时间:2023年03月03日

  • License:CC-BY-NC-SA 4.0 (转载请注明作者及来源)

1. 数学中的相等关系

在初中数学中,会介绍到什么是相等关系(也叫等价关系),相等关系是一种基本的二元关系,它描述了两个对象之间的相等性质。它必须满足如下三个性质:

  • 自反性(反身性):自己一定等于自己,即a=a

  • 对称性:若有a=b,则有b=a

  • 传递性:若有a=bb=c,则有a=c

也就是说,满足这三个性质才叫满足(完全)相等关系。这很容易理解,就不过多解释。

1.1 部分相等关系

对于简单的整数类型、字符串类型,我们可以说它们具有完全相等关系,因为它们可以全方位比较(包含两个维度,第一个是类型空间中的任意值,第二个是每个值的任意成员属性), 但是对于某些类型就不行了,这些类型总是不满足其中一个维度 。下面一起来看看:

以字符串为例,全方位比较的是它的每个字节值以及整个字符串的长度。

0. 浮点数类型

在浮点数类型中有个特殊的值是NaN(Not-a-number),这个值与任何值都不等(包括自己),它直接违背了自反性。这个时候,我们就需要为浮点数定义一种部分相等关系,这主要是为了比较非NaN浮点数。

NaN定义于IEEE 754-2008标准的5.2节“特殊值”(Special Values)中,除了NaN,另外两个特殊值是正无穷大(+infinity)、负无穷大(-infinity),不过这两个值满足自反性。

除了浮点数类型,数学中还有其他类型也不具有通常意义上的全等关系,比如集合类型、函数类型。

1. 集合类型

假设有集合A={1,2,3}、B={1,3,2},那么此时A和B是相等还是不相等呢?这就需要在不同角度去看待,当我们只关注集合中是否包含相同的元素时, 可以说它们相等,当我们还要严格要求元素顺序一致时,它们就不相等。

在实际应用中,由我们定义(Impl)了一种集合中的特殊相等关系,称为"集合的相等",这个特殊关系(实现逻辑)中,我们只要求两个集合的元素相同,不要求其他。

2. 函数类型

首先从浮点数的NaN角度来看函数,假设有函数A=f(x)、B=f(y),若x=y,那显然A的值也等于B,但是如果存在一个参数z是无意义的呢,意思是f(z)是无结果的或结果非法,那么此时可以说f(z)等于自身吗?那显然是不行的。这个例子和浮点数的例子是一个意思。

然后从集合类型的角度再来看一次函数,假设有函数A=f(x)、B=g(x),注意是两个不同的函数,当二者给定一个相同输入x产生相同结果时,此时f(x)和g(x)是相等还是不等呢?与集合类似,实际应用中,这里也是由我们定义(Impl)了一种函数中的特殊相等关系,称为函数的相等。这个特殊关系(实现逻辑)中,我们只要求两个函数执行结果的值相同,不要求函数执行过程相同。

1.2 部分相等与全相等的关系

部分相等是全相等关系的子集,也就是说,如果两个元素具有相等关系,那它们之间也一定有部分相等关系。这在编程语言中的实现也是同样遵循的规则。

1.3 小结

数学中定义了(全)相等关系(等价关系)的三大性质,分别是自反性、对称性和传递性;但某些数据类型中的值或属性违背了三大性质,就不能叫做满足全相等关系, 此时只能为该类型实现部分相等关系。

在部分相等关系中,用于比较的值也是满足三大性质的,因为此时我们排除了那些特殊值。另外,部分相等是全相等关系的子集。

2. 编程与数学的关系

数学是一门研究数据、空间和变化的庞大学科,它提供了一种严谨的描述和处理问题的方式,而编程则是将问题的解决方法转化为计算机程序的过程,可以说,数学是问题的理论形式, 编程则是问题的代码形式,编程解决问题的依据来自数学。

所以说,编程语言的设计中也是大量运用了数学概念与模型的,本文关注的相等关系就是一个例子。

在Rust库中的PartialEq的注释文档中提到了partial equivalence relations 即部分相等关系这一概念,并且同样使用了浮点数的特殊值NaN来举例说明。

Eq的注释文档则是提到了equivalence relations,并且明确说明了,对于满足Eqtrait的类型,是一定满足相等关系的三大性质的。

3. PartialEq

3.1 trait定义

Rust中的PartialEq的命名明确地表达了它的含义,但如果我们忘记了数学中的相等关系,就肯定会对此感到疑惑。先来看看它的定义:

pub trait PartialEq<Rhs: ?Sized = Self> {
    fn eq(&self, other: &Rhs) -> bool;
    fn ne(&self, other: &Rhs) -> bool {
        !self.eq(other)
    }
}

在这个定义中,可以得到三个基本信息:

  1. 这个trait包含2个方法,eq和ne,且ne具有默认实现,使用时开发者只需要实现eq方法即可(库文档也特别说明,若没有更好的理由,则不应该手动实现ne方法);

  2. PartialEq绑定的Rhs参数类型是?Size,即包括动态大小类型(DST)和固定大小类型(ST)类型(Rhs是主类型用来比较的类型);

  3. Rhs参数提供了默认类型即Self(和主类型一致),但也可以是其他类型,也就是说,实践中你甚至可以将i32与struct进行比较,只要实现了对应的PartialEq

Rust中的lhs和rhs指的是,"left-hand side"(左手边) 和 "right-hand side"(右手边)的参数。

3.

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值