GitHub: https://github.com/storagezhang

Emai: debugzhang@163.com

华为云社区: https://bbs.huaweicloud.com/blogs/250275

Eq and PartialEq are traits that allow you to define total and partial equality between values, respectively. Implementing them overloads the == and != operators.

PartialEq

  1. /// [`eq`]: PartialEq::eq
  2. /// [`ne`]: PartialEq::ne
  3. #[lang = "eq"]
  4. #[stable(feature = "rust1", since = "1.0.0")]
  5. #[doc(alias = "==")]
  6. #[doc(alias = "!=")]
  7. #[rustc_on_unimplemented(
  8. message = "can't compare `{Self}` with `{Rhs}`",
  9. label = "no implementation for `{Self} == {Rhs}`"
  10. )]
  11. pub trait PartialEq<Rhs: ?Sized = Self> {
  12. /// This method tests for `self` and `other` values to be equal, and is used
  13. /// by `==`.
  14. #[must_use]
  15. #[stable(feature = "rust1", since = "1.0.0")]
  16. fn eq(&self, other: &Rhs) -> bool;
  17. /// This method tests for `!=`.
  18. #[inline]
  19. #[must_use]
  20. #[stable(feature = "rust1", since = "1.0.0")]
  21. fn ne(&self, other: &Rhs) -> bool {
  22. !self.eq(other)
  23. }
  24. }

如果我们想比较某个类型的两个值 x 和 y 是否相等(不等),例如:x == y (x != y),那么我们就必须为类型实现 PartialEq Trait

PartialEq 可使用 #[derive] 来交由编译器实现,当一个 struct 在进行相等比较时,会对其中每一个字段进行比较;如果遇到枚举时,还会对枚举所拥有的数据进行比较。

我们也可以自己实现 PartialEq,实现时只需要实现判断是否相等的函数 fn eq(&self, other: &Self) -> bool ,Rust 会自动提供 fn ne(&self, other: &Self) -> bool。例子如下:

  1. enum BookFormat {
  2. Paperback,
  3. Hardback,
  4. Ebook,
  5. }
  6. struct Book {
  7. isbn: i32,
  8. format: BookFormat,
  9. }
  10. impl PartialEq for Book {
  11. fn eq(&self, other: &Self) -> bool {
  12. self.isbn == other.isbn
  13. }
  14. }

Eq

  1. pub trait Eq: PartialEq<Self> {
  2. // this method is used solely by #[deriving] to assert
  3. // that every component of a type implements #[deriving]
  4. // itself, the current deriving infrastructure means doing this
  5. // assertion without using a method on this trait is nearly
  6. // impossible.
  7. //
  8. // This should never be implemented by hand.
  9. #[doc(hidden)]
  10. #[inline]
  11. #[stable(feature = "rust1", since = "1.0.0")]
  12. fn assert_receiver_is_total_eq(&self) {}
  13. }

实现 Eq 的前提是已经实现了 PartialEq,因为实现 Eq 不需要额外的代码,只需要在实现了PartialEq 的基础上告诉编译器它的比较满足自反性就可以了。对于上面的例子只需要:#[derive(Eq)]impl Eq for Book {}

  1. enum BookFormat {
  2. Paperback,
  3. Hardback,
  4. Ebook,
  5. }
  6. struct Book {
  7. isbn: i32,
  8. format: BookFormat,
  9. }
  10. impl PartialEq for Book {
  11. fn eq(&self, other: &Self) -> bool {
  12. self.isbn == other.isbn
  13. }
  14. }
  15. impl Eq for Book {}

PartialEq 和 Eq

这两个 Traits 的名称实际上来自于抽象代数中的等价关系和局部等价关系。

等价关系(equivalence relation)即设 \(\displaystyle R\) 是某个集合 \(\displaystyle A\) 上的一个二元关系。若 \(\displaystyle R\) 满足以下条件:

  1. 自反性:\(\displaystyle \forall x\in A,~~xRx\)
  2. 对称性:\(\displaystyle \forall x,y\in A,~~xRy~~\implies ~~yRx\)
  3. 传递性:\(\displaystyle \forall x,y,z\in A,~~~(xRy~~\wedge ~~yRz)~~\implies ~~xRz\)

则称 \(\displaystyle R\) 是一个定义在 \(\displaystyle A\) 上的等价关系

并非所有的二元关系都是等价关系, EqPartialEq 的区别在于是否在相等比较中是否满足自反性,即 x == x

例如对于浮点类型,Rust 只实现了 PartialEq 而没有实现 Eq,原因在于 NaN != Nan,不满足自反性。

Eq 相比 PartialEq 需要额外满足自反性,即 a == a,对于浮点类型,Rust 只实现了 PartialEq 而不是 Eq,原因就是 NaN != NaN

Eq 和 Hash

当一个类型同时实现了 Eq 和 Hash 时,该类型满足下列特性:

  1. k1 == k2 -> hash(k1) == hash(k2)

即,当两个 key 相等时,它们的哈希值必然相等。Rust 里的 HashMap 和 HashSet 都依赖该特性。

Rust 内置 trait :PartialEq 和 Eq的更多相关文章

  1. 实践解析丨Rust 内置 trait:PartialEq 和 Eq

    摘要:Rust 在很多地方使用了 traits, 从非常浅显的操作符重载, 到 Send, Sync 这种非常微妙的特性. Rust 在很多地方使用了 traits, 从非常浅显的操作符重载, 到 S ...

  2. Python进阶-XVIV 类的内置方法:__str__ 、__repr__、析构函数(__del__)、双下的call,eq,new,hash 以及item相关的三个方法

    类的内置方法 它与内置函数有紧密的联系,有的内置函数就是调用的内置方法. 在顶级父类obj中有: 两个双下方法 obj.__str__ str(obj) obj.__repr__ repr(obj) ...

  3. Perl语言中一些内置变量等,$x、qw、cmp、eq、ne等

    转载 Perl语言中一些内置变量等,$x.qw.cmp.eq.ne等 字母 符号 释义 eq  = = equal(等于) ne != not equal(不等于) cmp 比较 qq  " ...

  4. TODO:Laravel 内置简单登录

    TODO:Laravel 内置简单登录 1. 激活Laravel的Auth系统Laravel 利用 PHP 的新特性 trait 内置了非常完善好用的简单用户登录注册功能,适合一些不需要复杂用户权限管 ...

  5. php 内置支持的标签和属性

    内置支持的标签和属性列表如下: 标签名 作用 包含属性 include 包含外部模板文件(闭合) file import 导入资源文件(闭合 包括js css load别名) file,href,ty ...

  6. thinkphp 内置标签volist 控制换行

    thinkphp 内置标签volist 控制换行 volist标签通常用于查询数据集(select方法)的结果输出,通常模型的select方法返回的结果是一个二维数组,可以直接使用volist标签进行 ...

  7. include(thinkphp常用内置标签)

    变量输出使用普通标签就足够了,但是要完成其他的控制.循环和判断功能,就需要借助模板引擎的标签库功能了,系统内置标签库的所有标签无需引入标签库即可直接使用. XML标签有两种,包括闭合标签和开放标签,一 ...

  8. 前端MVC学习总结(三)——AngularJS服务、路由、内置API、jQueryLite

    一.服务 AngularJS功能最基本的组件之一是服务(Service).服务为你的应用提供基于任务的功能.服务可以被视为重复使用的执行一个或多个相关任务的代码块. AngularJS服务是单例对象, ...

  9. ThinkPHP中的内置标签

    ThinkPHP中的内置标签 1.内置标签分类 闭合标签 <tag></tag> 开放标签 <tag /> 2.包含文件标签 主要功能:实现对文件的包含(类似于re ...

随机推荐

  1. vue watcher errors

    vue watcher errors Error in callback for watcher TypeError: Cannot set property of undefined" n ...

  2. web 前端工具: Gulp 使用教程

    1 1 1 Gulp 使用教程: 1 1 1 1 1 1 1 1 ERROR: ./app.js 当前目录路径: ./ 当前目录路径: ./ 1 1 1 1 1 参考资源: http://webpac ...

  3. Array.fill & array padding

    Array.fill & array padding arr.fill(value[, start[, end]]) https://developer.mozilla.org/en-US/d ...

  4. css & object-fit & background-image

    css & object-fit & background-image object-fit /*default fill */ object-fit: fill|contain|co ...

  5. axios upload excel file

    axios upload excel file https://github.com/axios/axios/issues/1660 https://stackoverflow.com/questio ...

  6. vue 使用stylus

    λ yarn add stylus stylus-loader --dev <style scoped lang="stylus"> div color #ff4488 ...

  7. element-ui的树型结构图,带有复选框的,没有子项的,横排展示

    // 修改树形图样式,如果不含有下箭头的块,要变成行内样式 treeChildInline(){ let hasCaretRight = $("#permission_panel" ...

  8. 我眼中的价值币——NGK(下)

    跨链交互方案并不是区块链世界中的一个新课题.自比特币诞生揭开智能合约的序幕之后,跨链交互的需求便产生了.但是,经过十年的发展,市场中的跨链解决方案进展缓慢,究之原因有以下几个方面. 首先,区块链的去中 ...

  9. 「NGK每日快讯」12.18日NGK公链第45期官方快讯!

  10. 为什么NGK推出的DEFI项目这么火热?

    进入到2020年的下半年,DeFi的锁仓量基本上是以日破新高的态势,不断的成为一个独角兽.DeFi逐渐形成一个独角兽的同时,也在不断的给区块链生态赋能,源源不断进行金融价值输送.所以加密货币体量的不断 ...