zoukankan      html  css  js  c++  java
  • 实践解析丨Rust 内置 trait:PartialEq 和 Eq

    摘要: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

     

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

  • 相关阅读:
    Unity--截取屏幕任意区域
    IOS 提交审核,遇到Missing Push Notification Entitlement 问题。
    VSync Count 垂直同步
    unity3d 自动保存
    首次发布App,In-App Purchase 无法submit for review 问题的解决方案
    国内银行CNAPS CODE 查询
    苹果开发——App内购以及验证store的收据(二)
    C#
    AJAX
    SQLite连接C#笔记
  • 原文地址:https://www.cnblogs.com/huaweiyun/p/14568911.html
Copyright © 2011-2022 走看看