matches! în Rust

Returnează true dacă o valoare se potrivește cu un tipar (ca într-o ramură de match) și false altfel.

Sintaxă
matches!(valoare, Tipar)                   // -> bool
matches!(valoare, Tipar1 | Tipar2)
matches!(valoare, Tipar if conditie)

Ce face matches!

matches!(x, tipar) este o prescurtare pentru match x { tipar => true, _ => false }. Este util când vrei doar să afli dacă o valoare are o anumită formă, fără să scoți date din ea: „este o literă de la a la f?”, „este varianta Livrata?”.

Poți folosi orice tipar acceptat de match: intervale ('a'..='z'), alternative cu |, variante de enum cu .. sau _ și o gardă cu if. Spre deosebire de ==, nu cere ca tipul să implementeze PartialEq.

Rezultatul este un bool, deci se folosește des în filter, any, all sau assert!.

Ce returnează

true dacă valoarea se potrivește cu tiparul (și garda este adevărată), altfel false.

Exemple

Exemplul 1: Caractere și numere

Un cod de culoare hexazecimal este valid dacă are 6 caractere și toate sunt cifre sau litere de la a la f.

fn este_hex(c: char) -> bool {
    matches!(c, '0'..='9' | 'a'..='f' | 'A'..='F')
}

fn main() {
    for cod in ["0057b7", "FFD700", "12g4zz", "abc"] {
        let valid = cod.len() == 6 && cod.chars().all(este_hex);
        println!("#{cod}: {}", if valid { "valid" } else { "invalid" });
    }
    let nota = 7;
    println!("trecut: {}", matches!(nota, 5..=10));
}

Rezultat

#0057b7: valid
#FFD700: valid
#12g4zz: invalid
#abc: invalid
trecut: true

Exemplul 2: Variante de enum și gărzi

matches! numără comenzile livrate și comenzile mari în așteptare, fără PartialEq pe Stare.

enum Stare {
    Noua { valoare: u32 },
    Expediata(String),
    Livrata,
}

fn main() {
    let comenzi = [
        Stare::Livrata,
        Stare::Noua { valoare: 1200 },
        Stare::Expediata("Sameday".to_string()),
        Stare::Noua { valoare: 80 },
        Stare::Livrata,
    ];
    let livrate = comenzi.iter().filter(|c| matches!(c, Stare::Livrata)).count();
    let mari_noi = comenzi.iter()
        .filter(|c| matches!(c, Stare::Noua { valoare } if *valoare > 1000))
        .count();
    let in_drum = comenzi.iter().any(|c| matches!(c, Stare::Expediata(_)));
    println!("livrate: {livrate}, noi peste 1000 lei: {mari_noi}, în drum: {in_drum}");
    if let Some(Stare::Expediata(curier)) = comenzi.iter().find(|c| matches!(c, Stare::Expediata(_))) {
        println!("curier: {curier}");
    }
}

Rezultat

livrate: 2, noi peste 1000 lei: 1, în drum: true
curier: Sameday

Greșeli frecvente

  • Încerci să folosești variabilele din tipar după matches!: if matches!(x, Some(v)) { println!("{v}") } nu se compilează. Pentru a scoate valoarea folosește if let Some(v) = x.
  • Scrii matches!(x, LIMITA) cu LIMITA variabilă locală: un nume simplu în tipar creează o legătură nouă care potrivește orice. Folosește o gardă: matches!(x, v if v == limita).

Comenzi înrudite

  • match: Compară o valoare cu o listă de tipare și execută ramura primului care se potrivește. Compilatorul verifică dacă toate cazurile sunt tratate.
  • pattern matching (tipare): Tiparele descriu forma unei valori și scot din ea părțile de care ai nevoie: în let, match, if let, for și parametrii funcțiilor.
  • if let și let else: if let execută un bloc doar dacă o valoare se potrivește cu un tipar; let else desface valoarea sau iese imediat din funcție.
  • enum: Definește un tip care poate fi exact una dintre mai multe variante; fiecare variantă poate avea propriile date.