Iterators

sum() and product()

The .sum() and .product() consumer methods compute the arithmetic sum or product of all elements in an iterator by delegating to the std::iter::Sum and std::iter::Product traits.

Signatures and Trait Definitions

fn sum<S>(self) -> S
where
    Self: Sized,
    S: Sum<Self::Item>;

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

Standard integer and floating-point types (i8..i128, isize, u8..u128, usize, f32, f64, and Wrapping<T>) implement Sum<T>, Sum<&T>, Product<T>, and Product<&T>, meaning both owned iterators (.into_iter()) and borrowed iterators (.iter()) can be summed or multiplied directly:

Method Empty Iterator Return Value Works on Item = T and Item = &T?
.sum::<T>() 0 (or 0.0 for floats) Yes
.product::<T>() 1 (or 1.0 for floats) Yes
fn main() {
    let values = [2_i32, 3, 4, 5];
    let empty: [i32; 0] = [];

    let total: i32 = values.iter().sum();
    let factorial: i32 = values.iter().product();

    println!("Sum:            {total}");
    println!("Product:        {factorial}");
    println!("Empty sum:      {}", empty.iter().sum::<i32>());
    println!("Empty product:  {}", empty.iter().product::<i32>());
}
Sum:            14
Product:        120
Empty sum:      0
Empty product:  1

Summing Fallible Iterators (Result<T, E> and Option<T>)

Just like FromIterator, both Result<T, E> (where T: Sum) and Option<T> (where T: Sum) implement Sum. This allows you to sum an iterator yielding Result<i32, E> directly into a Result<i32, E> without allocating an intermediate Vec<i32>, short-circuiting on the first Err:

use std::num::ParseIntError;

fn sum_csv_numbers(cells: &[&str]) -> Result<i64, ParseIntError> {
    cells.iter().map(|s| s.parse::<i64>()).sum()
}

fn main() {
    println!("Valid CSV:   {:?}", sum_csv_numbers(&["10", "25", "65"]));
    println!("Invalid CSV: {:?}", sum_csv_numbers(&["10", "bad", "65"]));
}
Valid CSV:   Ok(100)
Invalid CSV: Err(ParseIntError { kind: InvalidDigit })

Implementing Sum for a Custom Domain Type

use std::iter::Sum;

#[derive(Debug, Clone, Copy)]
struct DurationMs(u64);

impl Sum for DurationMs {
    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
        DurationMs(iter.map(|d| d.0).sum())
    }
}

fn main() {
    let intervals = [DurationMs(120), DurationMs(80), DurationMs(300)];
    let total: DurationMs = intervals.into_iter().sum();
    println!("Total duration: {total:?}");
}
Total duration: DurationMs(500)