Eq în Rust

Trait marker care promite egalitate completă (a == a mereu); cerut de chei în HashMap/HashSet și de Ord.

Sintaxă
#[derive(PartialEq, Eq)]
struct Tip { ... }

pub trait Eq: PartialEq { }

Ce face Eq

Eq nu are metode. Adaugă doar promisiunea că egalitatea din PartialEq este „completă”: orice valoare este egală cu ea însăși, iar regulile obișnuite (simetrie, tranzitivitate) se respectă. Numerele întregi, bool, char, String sunt Eq; f32 și f64 nu sunt, din cauza lui NaN.

Contează pentru că unele structuri cer această garanție: cheile din HashMap și HashSet trebuie să fie Eq + Hash, iar Ord (ordonarea totală) cere Eq. De aceea o structură cu un câmp f64 nu poate deriva Eq și nu poate fi cheie directă într-un HashMap.

Ce returnează

Nu are metode; se derivă împreună cu PartialEq.

Exemple

Exemplul 1: Chei proprii într-un HashMap

use std::collections::HashMap;

#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug, PartialOrd, Ord)]
enum Judet {
    Iasi,
    Cluj,
    Timis,
}

fn main() {
    let mut populatie: HashMap<Judet, u32> = HashMap::new();
    populatie.insert(Judet::Iasi, 760_774);
    populatie.insert(Judet::Cluj, 679_141);
    populatie.insert(Judet::Timis, 650_533);

    let mut chei: Vec<_> = populatie.keys().copied().collect();
    chei.sort();
    for j in chei {
        println!("{j:?}: {}", populatie[&j]);
    }
}

Rezultat

Iasi: 760774
Cluj: 679141
Timis: 650533

Exemplul 2: Implementare manuală și de ce f64 nu este Eq

Pentru un tip propriu cu PartialEq scris de mână, impl Eq for Tip {} este suficient. Pentru f64, NaN nu este egal cu el însuși, deci promisiunea lui Eq nu poate fi ținută.

struct Cod(String);

impl PartialEq for Cod {
    fn eq(&self, other: &Self) -> bool {
        self.0.eq_ignore_ascii_case(&other.0)
    }
}

impl Eq for Cod {}

fn este_eq<T: Eq>(_: &T) -> &'static str {
    "da"
}

fn main() {
    let a = Cod("ro-is".to_string());
    let b = Cod("RO-IS".to_string());
    println!("egale: {}, Cod este Eq: {}", a == b, este_eq(&a));
    let x = f64::NAN;
    println!("x == x pentru NaN: {}", x == x);
}

Rezultat

egale: true, Cod este Eq: da
x == x pentru NaN: false

Greșeli frecvente

  • Derivezi Eq pe o structură cu f64: the trait bound `f64: Eq` is not satisfied. Păstrează doar PartialEq sau ține valoarea ca întreg (de exemplu prețul în bani).
  • Derivezi Eq fără PartialEq: Eq îl cere ca bază.

Comenzi înrudite

  • PartialEq: Trait-ul din spatele operatorilor == și !=; derive compară toate câmpurile, implementarea manuală alege criteriul.
  • Hash: Trait-ul care transformă o valoare într-un hash; necesar (alături de Eq) pentru chei în HashMap și HashSet.
  • Ord: Ordonare totală: orice două valori se pot compara. cmp() returnează Ordering; necesar pentru sort(), BTreeMap, max().