Option::unwrap_or în Rust

Option: valori care pot lipsi Rust 1.0 (unwrap_or_default: 1.16)

Scoate valoarea din Some sau, pentru None, folosește o valoare de rezervă: fixă, calculată de o funcție sau implicită.

Sintaxă
fn unwrap_or(self, default: T) -> T
fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T
fn unwrap_or_default(self) -> T  // T: Default

Ce face Option::unwrap_or

Aceste trei metode scot valoarea din Some fără risc de panică. Diferența este ce returnează pentru None:

unwrap_or(valoare) returnează valoarea dată. unwrap_or_else(|| ...) apelează funcția (closure-ul) doar dacă este nevoie, deci e potrivită când valoarea de rezervă se calculează greu. unwrap_or_default() returnează valoarea implicită a tipului: 0 pentru numere, "" pentru String, vector gol pentru Vec, false pentru bool.

Argumentul lui unwrap_or este calculat întotdeauna, chiar dacă opțiunea este Some. Dacă acel argument este un apel de funcție costisitor, folosește unwrap_or_else.

Parametri

Parametru Descriere
default Valoarea returnată pentru None (la unwrap_or).
f Funcția fără argumente care produce valoarea de rezervă (la unwrap_or_else). Este apelată doar pentru None.

Ce returnează

Valoarea din Some sau valoarea de rezervă. Tipul este mereu T.

Exemple

Exemplul 1: Valoare implicită pentru setări lipsă

parse().ok() transformă textul într-un Option; textul invalid devine None, iar unwrap_or pune 5.

fn main() {
    let setari = ["10", "abc", ""];
    for text in setari {
        let pagini: u32 = text.parse().ok().unwrap_or(5);
        println!("{text:?} -> {pagini} articole pe pagină");
    }

    let porecla: Option<String> = None;
    println!("Porecla: {:?}", porecla.unwrap_or_default());

    let varsta: Option<u32> = None;
    println!("Vârsta: {}", varsta.unwrap_or_default());
}

Rezultat

"10" -> 10 articole pe pagină
"abc" -> 5 articole pe pagină
"" -> 5 articole pe pagină
Porecla: ""
Vârsta: 0

Exemplul 2: unwrap_or_else apelează funcția doar la nevoie

Pentru Some, funcția oras_implicit nu este apelată deloc; mesajul ei apare o singură dată, pentru None.

fn oras_implicit() -> String {
    println!("  (calculez orașul implicit...)");
    String::from("București")
}

fn main() {
    let din_profil: Option<String> = Some(String::from("Iași"));
    let lipsa: Option<String> = None;

    let a = din_profil.unwrap_or_else(oras_implicit);
    println!("a = {a}");

    let b = lipsa.unwrap_or_else(oras_implicit);
    println!("b = {b}");

    let c = None.unwrap_or_else(|| 2 + 2);
    println!("c = {c}");
}

Rezultat

a = Iași
  (calculez orașul implicit...)
b = București
c = 4

Greșeli frecvente

  • Scrii x.unwrap_or(calcul_lent()): calcul_lent rulează și când x este Some. Folosește x.unwrap_or_else(calcul_lent).
  • Încerci unwrap_or_default() pe un tip propriu fără Default. Adaugă #[derive(Default)] sau implementează trait-ul.
  • Dai la unwrap_or o valoare de alt tip: pentru Option<String> trebuie String::from("..."), nu "..." (care este &str).

Comenzi înrudite

  • Option::unwrap: Scoate valoarea din Some; pentru None programul se oprește cu panică. expect face la fel, cu mesajul tău.
  • Option::or: Dacă opțiunea este None, încearcă altă opțiune; Some rămâne neschimbat. or_else calculează alternativa doar la nevoie.
  • Result::unwrap_or: Scoate valoarea din Ok sau, la eroare, folosește o valoare de rezervă: fixă, calculată din eroare sau implicită.
  • Option::get_or_insert_with: Dacă opțiunea este None, pune în ea valoarea calculată de funcție; apoi returnează o referință mutabilă la valoare.