Option::filter în Rust

Option: valori care pot lipsi Rust 1.27 (is_some_and: 1.70)

filter păstrează valoarea doar dacă respectă o condiție; is_some_and întreabă direct dacă există și respectă condiția.

Sintaxă
fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Option<T>
fn is_some_and(self, f: impl FnOnce(T) -> bool) -> bool

Ce face Option::filter

filter(|x| condiție) returnează Some(x) doar dacă opțiunea este Some și condiția este adevărată pentru x. Altfel returnează None. Funcția primește o referință (&T).

is_some_and(|x| condiție) răspunde direct cu bool: este Some și valoarea respectă condiția? Înlocuiește formula mai lungă matches!(x, Some(v) if ...) sau x.map_or(false, |v| ...).

Parametri

Parametru Descriere
predicate Condiția verificată pe valoarea din Some.

Ce returnează

filter: Option<T>. is_some_and: bool (pentru None, mereu false).

Exemple

Exemplul 1: Păstrează doar valorile valide

O notă citită din text este acceptată doar dacă este între 1 și 10.

fn citeste_nota(text: &str) -> Option<u8> {
    text.trim().parse::<u8>().ok().filter(|n| (1..=10).contains(n))
}

fn main() {
    for text in ["9", "12", "abc", " 10 "] {
        println!("{text:?} -> {:?}", citeste_nota(text));
    }
}

Rezultat

"9" -> Some(9)
"12" -> None
"abc" -> None
" 10 " -> Some(10)

Exemplul 2: Întrebare da/nu cu is_some_and

Verificăm dacă un client are reducere: trebuie să aibă vârstă completată și să fie peste 65 de ani.

struct Client {
    nume: &'static str,
    varsta: Option<u32>,
}

fn main() {
    let clienti = [
        Client { nume: "Elena", varsta: Some(70) },
        Client { nume: "Andrei", varsta: Some(30) },
        Client { nume: "Maria", varsta: None },
    ];
    for c in &clienti {
        let reducere = c.varsta.is_some_and(|v| v >= 65);
        println!("{}: reducere = {reducere}", c.nume);
    }
}

Rezultat

Elena: reducere = true
Andrei: reducere = false
Maria: reducere = false

Greșeli frecvente

  • În filter uiți că primești &T: filter(|n| n > 5) nu compilează pentru numere; scrie filter(|n| *n > 5) sau filter(|&n| n > 5).
  • Folosești is_some_and pe o opțiune pe care o mai folosești după: metoda consumă opțiunea dacă tipul nu este Copy. Apelează-o pe x.as_ref().

Comenzi înrudite

  • Option::map: Transformă valoarea din Some cu o funcție și păstrează None neschimbat.
  • Option: Tipul care spune „poate există o valoare, poate nu”: Some(valoare) sau None, în locul lui null din alte limbaje.
  • Result::is_ok_and: Răspunde cu true dacă rezultatul este Ok și valoarea respectă condiția dată.
  • Option::as_ref: Transformă &Option<T> în Option<&T> (sau Option<&mut T>), ca să folosești valoarea fără să o muți din opțiune.