274: Numeric Reductions: sum() and product()
Functional Programming
Tutorial
The Problem
Summing or multiplying all elements of a collection is one of the most fundamental computational operations — from computing totals in spreadsheets to calculating factorials in mathematics, to aggregating metrics in monitoring systems. While these could be implemented with fold(), Rust provides sum() and product() as first-class methods that express intent clearly and can be implemented efficiently by the type system via the Sum and Product traits.
🎯 Learning Outcomes
sum() and product() as ergonomic specializations of fold for numeric typessum() returns zero and product() returns one for empty iterators (identity elements)sum() and product() on iterators of references by using .copied() or .cloned()Sum and Product traits for custom numeric typesCode Example
#![allow(clippy::all)]
//! 274. Numeric reductions: sum() and product()
//!
//! `sum()` and `product()` fold iterators of numbers with + and * respectively.
#[cfg(test)]
mod tests {
#[test]
fn test_sum_gauss() {
let sum: i32 = (1..=100).sum();
assert_eq!(sum, 5050);
}
#[test]
fn test_product_factorial() {
let fact5: u64 = (1u64..=5).product();
assert_eq!(fact5, 120);
}
#[test]
fn test_sum_empty() {
let s: i32 = Vec::<i32>::new().into_iter().sum();
assert_eq!(s, 0);
}
#[test]
fn test_product_empty() {
let p: i32 = Vec::<i32>::new().into_iter().product();
assert_eq!(p, 1); // identity element
}
}Key Differences
sum()/product() are generic over any type implementing Sum/Product; OCaml requires type-specific fold expressions.sum()/product() wrap on integer overflow in release mode; use checked_sum patterns or saturating arithmetic when needed.std::iter::Sum for a custom type lets it participate in sum() chains naturally.OCaml Approach
OCaml uses List.fold_left (+) 0 for sum and List.fold_left ( *) 1 for product — there are no dedicated functions:
let sum xs = List.fold_left (+) 0 xs
let product xs = List.fold_left ( * ) 1 xs
let () = assert (sum [1;2;3;4;5] = 15)
Base.List.sum and Base.List.product exist in Jane Street's Base library.
Full Source
#![allow(clippy::all)]
//! 274. Numeric reductions: sum() and product()
//!
//! `sum()` and `product()` fold iterators of numbers with + and * respectively.
#[cfg(test)]
mod tests {
#[test]
fn test_sum_gauss() {
let sum: i32 = (1..=100).sum();
assert_eq!(sum, 5050);
}
#[test]
fn test_product_factorial() {
let fact5: u64 = (1u64..=5).product();
assert_eq!(fact5, 120);
}
#[test]
fn test_sum_empty() {
let s: i32 = Vec::<i32>::new().into_iter().sum();
assert_eq!(s, 0);
}
#[test]
fn test_product_empty() {
let p: i32 = Vec::<i32>::new().into_iter().product();
assert_eq!(p, 1); // identity element
}
}
✓ Tests
Rust test suite
#[cfg(test)]
mod tests {
#[test]
fn test_sum_gauss() {
let sum: i32 = (1..=100).sum();
assert_eq!(sum, 5050);
}
#[test]
fn test_product_factorial() {
let fact5: u64 = (1u64..=5).product();
assert_eq!(fact5, 120);
}
#[test]
fn test_sum_empty() {
let s: i32 = Vec::<i32>::new().into_iter().sum();
assert_eq!(s, 0);
}
#[test]
fn test_product_empty() {
let p: i32 = Vec::<i32>::new().into_iter().product();
assert_eq!(p, 1); // identity element
}
}
Exercises
map(|x| x*x).sum::<i64>().product function for floating-point numbers that handles the case of any zero element by returning zero early.sum() and count() together to compute the arithmetic mean of a Vec<f64>.