Iterator::try_fold în Rust

Ca fold, dar funcția returnează Option sau Result și oprirea are loc la primul None sau Err.

Sintaxă
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
where F: FnMut(B, Self::Item) -> R, R: Try<Output = B>

Ce face Iterator::try_fold

try_fold funcționează ca fold, cu o diferență: closure-ul returnează Option<B> sau Result<B, E>. Cât timp primește Some / Ok, continuă cu valoarea din ele. La primul None sau Err, se oprește imediat și returnează acel rezultat; elementele rămase nu mai sunt procesate.

Este potrivit pentru calcule care pot eșua: adunare cu verificare de depășire (checked_add), parsare, validare. Primește iteratorul prin &mut, deci după o oprire timpurie poți continua de unde a rămas.

Parametri

Parametru Descriere
init Valoarea inițială.
f Closure care returnează Some(acc)/Ok(acc) pentru a continua sau None/Err(e) pentru a opri.

Ce returnează

Some(acc) / Ok(acc) dacă totul a reușit, altfel primul None / Err.

Exemple

Exemplul 1: Suma fără depășire

u8 merge doar până la 255. checked_add dă None la depășire, iar try_fold se oprește.

fn main() {
    let mici: [u8; 3] = [100, 50, 60];
    let mari: [u8; 3] = [100, 150, 60];
    println!("{:?}", mici.iter().try_fold(0u8, |acc, &x| acc.checked_add(x)));
    println!("{:?}", mari.iter().try_fold(0u8, |acc, &x| acc.checked_add(x)));
}

Rezultat

Some(210)
None

Exemplul 2: Totalul unui coș, cu eroare la primul preț greșit

fn total(preturi: &[&str]) -> Result<u32, String> {
    preturi.iter().try_fold(0, |acc, p| {
        let valoare: u32 = p.parse().map_err(|_| format!("preț invalid: {p:?}"))?;
        Ok(acc + valoare)
    })
}

fn main() {
    println!("{:?}", total(&["12", "30", "8"]));
    println!("{:?}", total(&["12", "treizeci", "8"]));
}

Rezultat

Ok(50)
Err("preț invalid: \"treizeci\"")

Greșeli frecvente

  • Folosești fold și verifici eroarea abia la final: continui inutil după primul eșec. try_fold se oprește imediat.
  • Uiți să înfășori rezultatul: closure-ul trebuie să returneze Some(acc) sau Ok(acc), nu doar acc.

Comenzi înrudite

  • Iterator::fold: Combină toate elementele într-o singură valoare, pornind de la o valoare inițială și aplicând o funcție pas cu pas.
  • Iterator::scan: Ca fold, dar produce câte un rezultat după fiecare element: o stare actualizată pas cu pas, de exemplu un total cumulat.
  • Iterator::collect: Consumă iteratorul și adună valorile într-o colecție: Vec, String, HashMap, HashSet, chiar Result sau Option.
  • Iterator::sum: sum adună toate elementele, product le înmulțește; tipul rezultatului trebuie precizat.