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

094: Peekable Iterator

Difficulty: Intermediate Category: Iterators Concept: Look-ahead with `Peekable<I>` Key Insight: Peekable lets you inspect the next element without consuming it โ€” essential for parsers and tokenizers
// 094: Peekable Iterator

fn dedup(v: &[i32]) -> Vec<i32> {
    let mut result = Vec::new();
    let mut iter = v.iter().peekable();
    while let Some(&val) = iter.next() {
        result.push(val);
        while iter.peek() == Some(&&val) { iter.next(); }
    }
    result
}

fn main() {
    println!("dedup: {:?}", dedup(&[1, 1, 2, 2, 2, 3, 3, 1]));

    // peek without consuming
    let v = vec![1, 2, 3];
    let mut iter = v.iter().peekable();
    assert_eq!(iter.peek(), Some(&&1));
    assert_eq!(iter.peek(), Some(&&1)); // still 1!
    assert_eq!(iter.next(), Some(&1));  // now consumed
    assert_eq!(iter.peek(), Some(&&2));
}

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

    #[test]
    fn test_dedup() {
        assert_eq!(dedup(&[1, 1, 2, 2, 2, 3, 3, 1]), vec![1, 2, 3, 1]);
        assert_eq!(dedup(&[]), Vec::<i32>::new());
        assert_eq!(dedup(&[5]), vec![5]);
    }

    #[test]
    fn test_peekable() {
        let mut iter = [1, 2, 3].iter().peekable();
        assert_eq!(iter.peek(), Some(&&1));
        assert_eq!(iter.next(), Some(&1));
        assert_eq!(iter.peek(), Some(&&2));
    }
}
(* 094: Peekable Iterator *)

(* OCaml: manual peekable wrapper *)
type 'a peekable = { mutable peeked: 'a option; seq: 'a Seq.t ref }

let make_peekable s = { peeked = None; seq = ref s }

let peek p =
  match p.peeked with
  | Some _ as v -> v
  | None ->
    match !(p.seq) () with
    | Seq.Nil -> None
    | Seq.Cons (x, rest) -> p.peeked <- Some x; p.seq := rest; Some x

let next p =
  match p.peeked with
  | Some x -> p.peeked <- None; Some x
  | None ->
    match !(p.seq) () with
    | Seq.Nil -> None
    | Seq.Cons (x, rest) -> p.seq := rest; Some x

(* Use: skip consecutive duplicates *)
let dedup s =
  let p = make_peekable s in
  let rec aux acc =
    match next p with
    | None -> List.rev acc
    | Some x ->
      (* skip while peek = x *)
      let rec skip () = match peek p with Some y when y = x -> ignore (next p); skip () | _ -> () in
      skip (); aux (x :: acc)
  in
  aux []

(* Tests *)
let () =
  let s = List.to_seq [1;1;2;2;2;3;3;1] in
  assert (dedup s = [1;2;3;1]);
  assert (dedup (List.to_seq []) = []);
  assert (dedup (List.to_seq [5]) = [5]);
  Printf.printf "โœ“ All tests passed\n"

๐Ÿ“Š Detailed Comparison

Core Insight

Peekable lets you inspect the next element without consuming it โ€” essential for parsers and tokenizers

OCaml Approach

  • See example.ml for implementation

Rust Approach

  • See example.rs for implementation

Comparison Table

FeatureOCamlRust
Seeexample.mlexample.rs