Iterator::sum în Rust

sum adună toate elementele, product le înmulțește; tipul rezultatului trebuie precizat.

Sintaxă
fn sum<S>(self) -> S
where S: Sum<Self::Item>

fn product<P>(self) -> P
where P: Product<Self::Item>

Ce face Iterator::sum

sum() returnează suma elementelor, product() produsul lor. Merg pentru toate tipurile numerice și pentru referințe la ele (v.iter().sum() pe &i32). Pentru un iterator gol, suma este 0 și produsul este 1.

Compilatorul are nevoie să știe tipul rezultatului: let s: i32 = v.iter().sum(); sau v.iter().sum::<i32>(). Depășirea valorii maxime oprește programul în modul de dezvoltare (debug); pentru calcule mari, folosește un tip mai mare (u64, u128).

Un iterator de Option<T> sau Result<T, E> poate fi adunat într-un Option<T> / Result<T, E>: dacă apare un None sau Err, acela este rezultatul. Este un consumator: parcurge iteratorul (sau doar cât are nevoie) și pornește lanțul de adaptoare leneșe din fața lui.

Ce returnează

Suma sau produsul, de tipul cerut.

Exemple

Exemplul 1: Total, medie și factorial

fn main() {
    let note = vec![9, 7, 10, 8];
    let suma: i32 = note.iter().sum();
    println!("suma = {suma}, media = {:.2}", suma as f64 / note.len() as f64);

    let factorial_10: u64 = (1..=10).product();
    println!("10! = {factorial_10}");

    let preturi = [5.5, 12.25, 3.0];
    println!("total: {:.2} lei", preturi.iter().sum::<f64>());
}

Rezultat

suma = 34, media = 8.50
10! = 3628800
total: 20.75 lei

Exemplul 2: Iterator gol, Option și Result

Suma unor Option este None dacă lipsește măcar o valoare; suma unor Result se oprește la prima eroare.

fn main() {
    let gol: [u32; 0] = [];
    println!("sumă goală: {}, produs gol: {}", gol.iter().sum::<u32>(), gol.iter().product::<u32>());

    let complete = [Some(3), Some(4)];
    let incomplete = [Some(3), None];
    println!("{:?} {:?}", complete.iter().copied().sum::<Option<u32>>(), incomplete.iter().copied().sum::<Option<u32>>());

    let total: Result<u32, _> = "10 20 x".split(' ').map(|s| s.parse::<u32>()).sum();
    println!("{:?}", total);
}

Rezultat

sumă goală: 0, produs gol: 1
Some(7) None
Err(ParseIntError { kind: InvalidDigit })

Greșeli frecvente

  • Scrii let s = v.iter().sum();: type annotations needed. Pune tipul variabilei sau sum::<i32>().
  • Calculezi media cu împărțire întreagă (suma / n) și pierzi zecimalele. Convertește: suma as f64 / n as f64.
  • Produsul crește foarte repede: (1..=25).product::<u64>() depășește u64 și oprește programul cu attempt to multiply with overflow. Folosește u128 sau checked_mul.

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::count: Parcurge iteratorul până la capăt și returnează câte elemente a produs.
  • Iterator::min: Returnează cel mai mic (min) sau cel mai mare (max) element, ca Option: None pentru un iterator gol.
  • Iterator::try_fold: Ca fold, dar funcția returnează Option sau Result și oprirea are loc la primul None sau Err.