๐Ÿฆ€ 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

286: Creating Iterators with from_fn()

Difficulty: 2 Level: Intermediate Create a stateful iterator from a closure โ€” the lightweight alternative to implementing the `Iterator` trait.

The Problem This Solves

You need a custom iterator but implementing a full struct with `Iterator` is overkill. You want to generate a Fibonacci sequence for a test. Parse tokens from a string one at a time. Simulate reading from a buffer. For these one-off sequences, defining a named struct feels like ceremony โ€” you name a type that's used once, define fields, implement a trait, and repeat a lot of boilerplate. `std::iter::from_fn` lets you skip all of that: pass a closure that captures its mutable state and returns `Option<T>`. Return `Some(value)` to yield, `None` to terminate. The closure is the iterator. In OCaml, you'd use `Seq.unfold` or `Seq.of_dispenser`. In Haskell, `unfoldr`. In Rust, `from_fn` is the direct equivalent for the case where each step doesn't need the previous value to compute the next.

The Intuition

`std::iter::from_fn(closure)` creates an iterator that calls the closure on each `next()`. The closure captures its mutable state in the closure environment. Return `Some(value)` to emit; return `None` to stop.
let mut n = 0;
let counter = std::iter::from_fn(move || {
 n += 1;
 if n <= 5 { Some(n) } else { None }
});
// โ†’ yields 1, 2, 3, 4, 5

How It Works in Rust

// Fibonacci โ€” state lives inside the closure (no struct needed)
let fib = {
 let (mut a, mut b) = (0u64, 1u64);
 std::iter::from_fn(move || {
     let val = a;
     let next = a + b;
     a = b;       // advance state
     b = next;
     Some(val)    // always Some โ€” infinite sequence, use take()
 })
};
let first_10: Vec<u64> = fib.take(10).collect();
// โ†’ [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

// Parse tokens one at a time from an external iterator
let input = "42 17 99 3 55";
let mut words = input.split_whitespace();
let numbers: Vec<u32> = std::iter::from_fn(|| {
 words.next().and_then(|w| w.parse().ok())  // None on parse fail or exhaustion
}).collect();
// โ†’ [42, 17, 99, 3, 55]

// Simulate buffer reads
let buffer = vec![1u8, 2, 3, 4, 5];
let mut idx = 0;
let reader = std::iter::from_fn(|| {
 if idx < buffer.len() {
     let v = buffer[idx];
     idx += 1;
     Some(v)
 } else {
     None
 }
});
let bytes: Vec<u8> = reader.collect();
`from_fn` requires the closure to be `FnMut` โ€” it's called repeatedly. Use `move` to capture owned state. For sequences where each element depends on the previous, also consider `successors()`.

What This Unlocks

Key Differences

ConceptOCamlRust
Iterator from closure`Seq.of_dispenser``std::iter::from_fn(closure)`
Infinite sequence`Seq.unfold``from_fn(Some(next))` + `.take(n)`
State storageClosure captures / `ref`Closure captures (via `move`)
vs. custom struct`Seq.unfold` is more general`from_fn` for no prev-value dependency; `successors` for chained
TerminationReturn `None` nodeReturn `None` from closure
//! # Creating Iterators with from_fn()
//!
//! `std::iter::from_fn(f)` creates an iterator from a closure returning `Option<T>`.

/// Create a simple counting iterator using from_fn
pub fn counter(max: i32) -> impl Iterator<Item = i32> {
    let mut n = 0;
    std::iter::from_fn(move || {
        n += 1;
        if n <= max {
            Some(n)
        } else {
            None
        }
    })
}

/// Create a Fibonacci iterator using from_fn
pub fn fibonacci() -> impl Iterator<Item = u64> {
    let (mut a, mut b) = (0u64, 1u64);
    std::iter::from_fn(move || {
        let val = a;
        let next = a.checked_add(b)?; // Return None on overflow
        a = b;
        b = next;
        Some(val)
    })
}

/// Parse numbers from whitespace-separated string
pub fn parse_numbers(input: &str) -> impl Iterator<Item = u32> + '_ {
    let mut words = input.split_whitespace();
    std::iter::from_fn(move || {
        loop {
            match words.next() {
                None => return None,
                Some(w) => {
                    if let Ok(n) = w.parse() {
                        return Some(n);
                    }
                    // skip invalid, continue to next word
                }
            }
        }
    })
}

/// Alternative: Create a range with custom step
pub fn stepped_range(start: i32, end: i32, step: i32) -> impl Iterator<Item = i32> {
    let mut current = start;
    std::iter::from_fn(move || {
        if (step > 0 && current < end) || (step < 0 && current > end) {
            let val = current;
            current += step;
            Some(val)
        } else {
            None
        }
    })
}

/// Create iterator from buffer simulation
pub fn buffer_reader(buffer: Vec<u8>) -> impl Iterator<Item = u8> {
    let mut idx = 0;
    std::iter::from_fn(move || {
        if idx < buffer.len() {
            let v = buffer[idx];
            idx += 1;
            Some(v)
        } else {
            None
        }
    })
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_counter() {
        let result: Vec<i32> = counter(5).collect();
        assert_eq!(result, vec![1, 2, 3, 4, 5]);
    }

    #[test]
    fn test_counter_zero() {
        let result: Vec<i32> = counter(0).collect();
        assert!(result.is_empty());
    }

    #[test]
    fn test_fibonacci_first_10() {
        let result: Vec<u64> = fibonacci().take(10).collect();
        assert_eq!(result, vec![0, 1, 1, 2, 3, 5, 8, 13, 21, 34]);
    }

    #[test]
    fn test_parse_numbers() {
        let result: Vec<u32> = parse_numbers("42 17 99 3 55").collect();
        assert_eq!(result, vec![42, 17, 99, 3, 55]);
    }

    #[test]
    fn test_parse_numbers_with_invalid() {
        let result: Vec<u32> = parse_numbers("1 foo 3 bar 5").collect();
        assert_eq!(result, vec![1, 3, 5]); // skips invalid
    }

    #[test]
    fn test_stepped_range() {
        let result: Vec<i32> = stepped_range(0, 10, 2).collect();
        assert_eq!(result, vec![0, 2, 4, 6, 8]);
    }

    #[test]
    fn test_stepped_range_negative() {
        let result: Vec<i32> = stepped_range(10, 0, -3).collect();
        assert_eq!(result, vec![10, 7, 4, 1]);
    }

    #[test]
    fn test_buffer_reader() {
        let result: Vec<u8> = buffer_reader(vec![1, 2, 3, 4, 5]).collect();
        assert_eq!(result, vec![1, 2, 3, 4, 5]);
    }
}
(* 286. Creating iterators with from_fn() - OCaml *)
(* OCaml Seq.unfold is the equivalent *)

let () =
  (* Simple counter *)
  let counter =
    let n = ref 0 in
    Seq.unfold (fun () ->
      if !n >= 5 then None
      else begin incr n; Some (!n, ()) end
    ) ()
  in
  List.iter (fun x -> Printf.printf "%d " x) (List.of_seq counter);
  print_newline ();

  (* Fibonacci *)
  let fib =
    let a = ref 0 and b = ref 1 in
    Seq.forever (fun () ->
      let v = !a in
      let next = !a + !b in
      a := !b; b := next; v
    )
  in
  Printf.printf "Fib: %s\n"
    (String.concat ", " (List.map string_of_int (List.of_seq (Seq.take 10 fib))));

  (* Reading tokens from a string *)
  let words = ["hello"; "world"; "rust"] in
  let idx = ref 0 in
  let word_iter =
    Seq.unfold (fun () ->
      if !idx >= List.length words then None
      else begin
        let w = List.nth words !idx in
        incr idx;
        Some (w, ())
      end
    ) ()
  in
  List.iter (fun w -> Printf.printf "%s " w) (List.of_seq word_iter);
  print_newline ()