Practice analysis of rust built-in trait: partialeq and EQ

Time:2021-4-14

Abstract:Rust uses traits in many places, from simple operator overloading to subtle features like send and sync.

This article is shared from Huawei cloud community《Analysis of rust built-in trait: partialeq and EQ》Author: debugzhang

Rust uses traits in many places, from simple operator overloading to subtle features like send and sync. Some traits can be automatically derived (you just need to write # [derive (copy, clone, partialeq, EQ, debug, default, hash,…)] to get a magical implementation, which is usually right.

The names of partialeq and EQ actually come from the equivalence relation and local equivalence relation in abstract algebra. In fact, there is only one difference between them, that is, whether reflexivity is satisfied in equality comparison.

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)
    }
}

If we want to compare two values X and y of a type to see if they are equal (unequal), for example, x = = y (x! = y), we must implement partialeq trait for the type.

Partialeq can be implemented by the compiler with # [derive]. When a struct makes an equal comparison, it will compare each field; if it encounters enumeration, it will also compare the data owned by the enumeration.

We can also implement partialeq by ourselves. We only need to implement the function fn EQ (& self, other: & self) – > bool to judge whether it is equal. Rust will automatically provide FN ne (& self, other: & self) – > bool. Examples are as follows:

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) {}
}

The premise of implementing EQ is that partialeq has been implemented, because the implementation of EQ does not need additional code, only need to tell the compiler that its comparison satisfies Reflexivity on the basis of implementing partial Eq. For the above example, you only need: # [derive (EQ)] or 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 and EQ

The names of these two traits actually come from the equivalence relation and local equivalence relation in abstract algebra.

equivalence relation (equivalence relation) that is, let R be displaystyle_ R_ Is a set displaystyle a_ A_ A binary relation on. If displaystyle R_ R_ The following conditions are met:

Practice analysis of rust built-in trait: partialeq and EQ

It is called displaystyle R_ R_ It is defined in displaystyle a_ A_ Onequivalence relation

Not all binary relations are equivalent. The difference between EQ and partialeq is whether they satisfy reflexivity in equality comparison, that is, x = = X.

For example, for floating-point types, rust only implements partialeq instead of EQ, because Nan! = Nan does not satisfy reflexivity.

Compared with partialeq, EQ needs additional reflexivity, that is, a = = A. for floating-point types, rust only implements partialeq instead of EQ, because Nan! = Nan.

EQ and hash

When a type implements EQ and hash at the same time, the type satisfies the following characteristics:

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

That is, when two keys are equal, their hash values must be equal. Both HashMap and HashSet in rust depend on this feature.

Click follow to learn about Huawei’s new cloud technology for the first time~