๐Ÿฆ€ Functional Rust
๐ŸŽฌ How Rust Iterators Work Lazy evaluation, chaining, collect(), and zero-cost abstractions.
๐Ÿ“ Text version (for readers / accessibility)

โ€ข Iterators are lazy โ€” .map(), .filter(), .take() build a chain but do no work until consumed

โ€ข .collect() triggers evaluation, transforming the chain into a Vec, HashMap, or other collection

โ€ข Zero-cost abstraction: iterator chains compile to the same machine code as hand-written loops

โ€ข .iter() borrows, .into_iter() consumes, .iter_mut() borrows mutably

โ€ข Chaining replaces nested loops with a readable, composable pipeline

274: Numeric Reductions: sum() and product()

Difficulty: 1 Level: Beginner Fold a numeric iterator to a single value using addition or multiplication.

The Problem This Solves

Adding up a list of numbers or computing their product are among the most common reductions in any program. You could write `.fold(0, |acc, x| acc + x)` โ€” but that exposes the identity element and the operator as boilerplate, and signals nothing about intent to the reader. `sum()` and `product()` remove all that noise. They're also more generic than they appear: both work on any type that implements the `Sum` or `Product` trait โ€” including `f64`, `u64`, `i32`, and even `Option<T>` (where a single `None` makes the whole sum `None`). You can map + sum in one expression: `scores.iter().map(|s| s * s).sum()`. In OCaml, you'd use `List.fold_left (+) 0` or `List.fold_left ( * ) 1`. In Rust, `sum()` and `product()` are the idiomatic one-word versions.

The Intuition

`sum()` reduces an iterator of numbers by adding them all together (identity: 0). `product()` multiplies them all (identity: 1). Both are zero-cost abstractions over `fold` โ€” the compiler produces identical machine code.
let nums = [1, 2, 3, 4, 5];
let total: i32 = nums.iter().sum();      // โ†’ 15
let prod: i32  = nums.iter().product();  // โ†’ 120

How It Works in Rust

let nums = [1i32, 2, 3, 4, 5];

// Basic sum and product
let total: i32 = nums.iter().sum();      // โ†’ 15
let prod: i32  = nums.iter().product();  // โ†’ 120

// Factorial: product over a range
let factorial = |n: u64| -> u64 { (1..=n).product() };
println!("{}", factorial(10));  // โ†’ 3628800

// Compose with map: sum of squares
let sum_squares: i32 = nums.iter().map(|&x| x * x).sum();  // โ†’ 55

// Float: total price and average
let prices = [9.99f64, 14.50, 3.75, 22.00];
let total_price: f64 = prices.iter().sum();
let avg = total_price / prices.len() as f64;

// Gauss formula check
let gauss: i32 = (1..=100).sum();
assert_eq!(gauss, 5050);

// Empty iterator returns the identity element
let empty_sum: i32 = vec![].into_iter().sum();      // โ†’ 0
let empty_prod: i32 = vec![].into_iter().product(); // โ†’ 1

// Option<T> sum: None if any element is None
let opts: Vec<Option<i32>> = vec![Some(1), Some(2), Some(3)];
let opt_sum: Option<i32> = opts.into_iter().sum();  // โ†’ Some(6)
The return type must be annotated or inferred โ€” `sum()` and `product()` are generic over the output type.

What This Unlocks

Key Differences

ConceptOCamlRust
Sum a list`List.fold_left (+) 0 lst``iter.sum::<i32>()`
Product a list`List.fold_left ( * ) 1 lst``iter.product::<i32>()`
Identity elementExplicit in foldImplicit (from `Sum`/`Product` trait)
Floating pointSameWorks โ€” `f32`, `f64` implement both
Empty collectionMust pass identity manuallyReturns identity element automatically
//! 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
    }
}
(* 274. Numeric reductions: sum() and product() - OCaml *)

let sum lst = List.fold_left (+) 0 lst
let product lst = List.fold_left ( * ) 1 lst

let () =
  let nums = [1; 2; 3; 4; 5] in
  Printf.printf "Sum: %d\n" (sum nums);
  Printf.printf "Product: %d\n" (product nums);

  let factorial n = product (List.init n (fun i -> i + 1)) in
  Printf.printf "5! = %d\n" (factorial 5);
  Printf.printf "10! = %d\n" (factorial 10);

  let sum_squares = sum (List.map (fun x -> x * x) nums) in
  Printf.printf "Sum of squares: %d\n" sum_squares;

  let prices = [9.99; 14.50; 3.75; 22.00] in
  let total = List.fold_left (+.) 0.0 prices in
  Printf.printf "Total: %.2f\n" total;
  Printf.printf "Average: %.2f\n" (total /. float_of_int (List.length prices))