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

Rust 在很多地方使用了 traits, 从非常浅显的操作符重载, 到 Send, Sync 这种非常微妙的特性。一些 traits 是可以被自动派生的(你只需要写#[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Hash, ...)] 就能得到一个神奇的实现, 它通常是对的。

PartialEq 和 Eq这两个 Traits 的名称实际上来自于抽象代数中的等价关系和局部等价关系,实际上两者的区别仅有一点,即是否在相等比较中是否满足反身性(Reflexivity)。

PartialEq

/// [`eq`]: PartialEq::eq
/// [`ne`]: PartialEq::ne
#[lang = "eq"]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "==")]
#[doc(alias = "!=")]
#[rustc_on_unimplemented(
message = "can't compare `{Self}` with `{Rhs}`",
label = "no implementation for `{Self} == {Rhs}`"
)]
pub trait PartialEq<Rhs: ?Sized = Self> {
/// This method tests for `self` and `other` values to be equal, and is used
/// by `==`.
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
fn eq(&self, other: &Rhs) -> bool; /// This method tests for `!=`.
#[inline]
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
fn ne(&self, other: &Rhs) -> bool {
!self.eq(other)
}
}

如果我们想比较某个类型的两个值 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。例子如下:

enum BookFormat {
Paperback,
Hardback,
Ebook,
} struct Book {
isbn: i32,
format: BookFormat,
} impl PartialEq for Book {
fn eq(&self, other: &Self) -> bool {
self.isbn == other.isbn
}
}

Eq

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

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

enum BookFormat {
Paperback,
Hardback,
Ebook,
} struct Book {
isbn: i32,
format: BookFormat,
} impl PartialEq for Book {
fn eq(&self, other: &Self) -> bool {
self.isbn == other.isbn
}
} impl Eq for Book {}

PartialEq 和 Eq

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

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

则称 \displaystyle RR 是一个定义在 \displaystyle AA 上的等价关系。

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

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

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

Eq 和 Hash

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

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

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

本文分享自华为云社区《Rust 内置 trait 解析:PartialEq 和 Eq》,原文作者:debugzhang

点击关注,第一时间了解华为云新鲜技术~

实践解析丨Rust 内置 trait:PartialEq 和 Eq的更多相关文章

  1. Rust 内置 trait :PartialEq 和 Eq

    GitHub: https://github.com/storagezhang Emai: debugzhang@163.com 华为云社区: https://bbs.huaweicloud.com/ ...

  2. node npm --save,不同JS解析器的内置全局变量,PROMISE,CONST---ES6

    npm  --save 当你为你的模块安装一个依赖模块时,正常情况下你得先安装他们(在模块根目录下npm install module-name),然后连同版本号手动将他们添加到模块配置文件packa ...

  3. OSG3.4内置Examples解析【目录】

    opengl渲染管线 从整体上解读OpenGL的渲染流程 一 从整体上解读OpenGL的渲染流程 二 osg与animate相关示例解析 OSG3.4内置Examples(osganimate)解析 ...

  4. jsp九个内置对象、四个域对象及Servlet的三大域对象

    一,什么是内置对象? 在jsp开发中会频繁使用到一些对象,如ServletContext HttpSession PageContext等.如果每次我们在jsp页面中需要使用这些对象都要自己亲自动手创 ...

  5. ES系列六、ES字段类型及ES内置analyzer分析

    一.背景知识 在Es中,字段的类型很关键: 在索引的时候,如果字段第一次出现,会自动识别某个类型,这种规则之前已经讲过了. 那么如果一个字段已经存在了,并且设置为某个类型.再来一条数据,字段的数据不与 ...

  6. 如何利用.Net内置类,解析未知复杂Json对象

    如何利用.Net内置类,解析未知复杂Json对象 如果你乐意,当然可以使用强大的第三方类库Json.Net中的JObject类解析复杂Json字串 . 我不太希望引入第三方类库,所以在.Net内置类J ...

  7. 2017年05月10日记一次微项目投产 | 安卓版微信内置浏览器不能解析gzip压缩过的mp4视频的问题

    前言 今天投产了一个小项目,一个很简单的H5,有播放视频功能,使用了videojs插件. 之前也做过数个视频播放,视频的转压都按照既定流程进行,文件放到FTP后,iphone和安卓机测试下来都没有问题 ...

  8. JavaWeb -jsp文件和内置对象的解析

    jsp文件和内置对象的解析 对page解析 JSP九大内置对象(自带,无需new) 1 out:输出对象 2 request:请求对象,存储“客户端像服务端发送的请求信息” 3 response:响应 ...

  9. SpringBoot 源码解析 (六)----- Spring Boot的核心能力 - 内置Servlet容器源码分析(Tomcat)

    Spring Boot默认使用Tomcat作为嵌入式的Servlet容器,只要引入了spring-boot-start-web依赖,则默认是用Tomcat作为Servlet容器: <depend ...

随机推荐

  1. Storybook 最新教程

    Storybook 最新教程 Storybook is the most popular UI component development tool for React, Vue, and Angul ...

  2. how to share UI components

    how to share UI components The shared component cloud · Bit https://bit.dev/ A better way to build w ...

  3. holy shit StackOverflow

    holy shit StackOverflow refs https://stackoverflow.com/users/5934465/xgqfrms?tab=questions xgqfrms 2 ...

  4. JavaScript Learning Paths(ES5/ES6/ES-Next)

    JavaScript Learning Paths(ES5/ES6/ES-Next) JavaScript Expert refs https://developer.mozilla.org/en-U ...

  5. idle & js

    idle & js idle meaning in js https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensi ...

  6. svg click event bug & css pointer-events

    svg click event bug & css pointer-events svg click event not working Error OK ??? css class /* d ...

  7. 【函数分享】每日PHP函数分享(2021-2-19)

    array_diff_uassoc - 用用户提供的回调函数做索引检查来计算数组的差集 说明 array_diff_uassoc ( array $array1 , array $array2 , a ...

  8. JavaScript 中的执行上下文和执行栈

    JavaScript - 原理系列 ​ 在日常开发中,每当我们接手一个现有项目后,我们总喜欢先去看看别人写的代码.每当我们看到别人写出很酷的代码的时候,我们总会感慨!写出这么优美而又简洁的代码的兄弟到 ...

  9. 1090 Highest Price in Supply Chain——PAT甲级真题

    1090 Highest Price in Supply Chain A supply chain is a network of retailers(零售商), distributors(经销商), ...

  10. 从跳频技术聊CDMA/WIFI之母海蒂·拉玛传奇的一生

    导语:本篇的内容都是 文末的参考文章摘要而来的,本人根据自己的癖好,以及对 海蒂·拉玛 人生的感慨整理成本文. "WiFi"之母的海蒂·拉玛在中国的知名度,比起克劳德·香农应该也不 ...