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

267: Infinite Cycling with cycle()

Difficulty: 2 Level: Intermediate Repeat a finite iterator endlessly โ€” round-robin scheduling, color cycling, repeating patterns.

The Problem This Solves

You need to pair each item in a longer list with elements from a shorter repeating pattern: assign roles in a round-robin, alternate row colors, apply repeating weights for a checksum. Without `cycle()`, you'd use modular indexing โ€” `pattern[i % pattern.len()]` โ€” which requires the pattern to be indexable (arrays, vecs) and scatters the logic through your code. Cycling is especially useful when `zip`-ping: pair each element of a long list with the corresponding element of a short list, wrapping around automatically. `cycle()` turns that into a single expression. OCaml doesn't have a built-in cycle for lists, but `Seq` supports infinite sequences. In Rust, `cycle()` works on any iterator that implements `Clone` โ€” the iterator is cloned at the start of each repetition.

The Intuition

`cycle()` returns an iterator that, once it reaches the end of the underlying sequence, resets to the beginning and starts again โ€” forever. Use `take(n)` or `zip()` to bound consumption.
let colors = ["red", "green", "blue"];
let cycled: Vec<_> = colors.iter().cycle().take(7).collect();
// โ†’ ["red", "green", "blue", "red", "green", "blue", "red"]

How It Works in Rust

let colors = ["red", "green", "blue"];

// Take a bounded prefix of the infinite cycle
let cycled: Vec<_> = colors.iter().cycle().take(9).collect();
// โ†’ [red, green, blue, red, green, blue, red, green, blue]

// Round-robin role assignment: zip a long list with a cycling short list
let items = ["a", "b", "c", "d", "e"];
let roles = ["leader", "follower"];
let assigned: Vec<String> = items.iter()
 .zip(roles.iter().cycle())               // cycle roles to match items length
 .map(|(item, role)| format!("{}->{}", item, role))
 .collect();
// โ†’ ["a->leader", "b->follower", "c->leader", "d->follower", "e->leader"]

// Alternating boolean pattern
let alternating: Vec<bool> = [true, false].iter().copied()
 .cycle().take(8).collect();
// โ†’ [true, false, true, false, true, false, true, false]

// Repeating weights for a checksum
let weights = [1u32, 3, 7];
let data = [4u32, 5, 6, 7, 8, 9];
let checksum: u32 = data.iter()
 .zip(weights.iter().cycle())
 .map(|(d, w)| d * w)
 .sum();
The inner iterator must implement `Clone` โ€” `cycle()` clones the iterator to replay it from the start each cycle.

What This Unlocks

Key Differences

ConceptOCamlRust
Infinite repetition`Seq.cycle` (OCaml 4.14+) / manual unfold`iter.cycle()`
Bound consumption`Seq.take n``.take(n)` or `.zip(finite_iter)`
Requires `Clone`N/AYes โ€” iterator cloned at each cycle boundary
Works on any iterator`Seq` onlyAny `Iterator + Clone`
//! 267. Infinite cycling with cycle()
//!
//! `cycle()` repeats a finite iterator infinitely. Requires `Clone` on the inner iterator.

fn main() {
    let colors = ["red", "green", "blue"];
    let cycled: Vec<_> = colors.iter().cycle().take(9).collect();
    println!("Cycled colors: {:?}", cycled);

    let items = ["a", "b", "c", "d", "e"];
    let roles = ["leader", "follower"];
    let assigned: Vec<_> = items.iter()
        .zip(roles.iter().cycle())
        .map(|(item, role)| format!("{}->{}", item, role))
        .collect();
    println!("Assigned: {:?}", assigned);

    let alternating: Vec<bool> = [true, false].iter().copied()
        .cycle().take(8).collect();
    println!("Alternating: {:?}", alternating);

    let weights = [1u32, 3, 7];
    let digits = [4u32, 5, 6, 7, 8, 9];
    let checksum: u32 = digits.iter()
        .zip(weights.iter().cycle())
        .map(|(d, w)| d * w)
        .sum();
    println!("Weighted checksum: {}", checksum);

    let days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
    let first_two: Vec<_> = days.iter().cycle().enumerate().take(14)
        .map(|(i, day)| format!("Day {}: {}", i+1, day))
        .collect();
    println!("First week: {:?}", &first_two[..7]);
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_cycle_basic() {
        let result: Vec<i32> = [1, 2, 3].iter().copied().cycle().take(7).collect();
        assert_eq!(result, vec![1, 2, 3, 1, 2, 3, 1]);
    }

    #[test]
    fn test_cycle_zip_round_robin() {
        let items = [1i32, 2, 3, 4];
        let labels = ["a", "b"];
        let paired: Vec<_> = items.iter().zip(labels.iter().cycle()).collect();
        assert_eq!(paired.len(), 4);
        assert_eq!(*paired[2].1, "a");
    }

    #[test]
    fn test_cycle_alternating() {
        let alt: Vec<bool> = [true, false].iter().copied().cycle().take(6).collect();
        assert_eq!(alt, vec![true, false, true, false, true, false]);
    }
}
(* 267. Infinite cycling with cycle() - OCaml *)

let cycle lst =
  let arr = Array.of_list lst in
  let n = Array.length arr in
  let i = ref 0 in
  Seq.forever (fun () -> let v = arr.(!i mod n) in incr i; v)

let () =
  let colors = ["red"; "green"; "blue"] in
  let cycled = cycle colors in
  let first9 = Seq.take 9 cycled |> List.of_seq in
  Printf.printf "Colors: %s\n" (String.concat ", " first9);

  let items = ["a"; "b"; "c"; "d"; "e"] in
  let roles = cycle ["leader"; "follower"] in
  let pairs = List.map2 (fun item role -> Printf.sprintf "%s->%s" item role)
    items (Seq.take 5 roles |> List.of_seq) in
  List.iter print_endline pairs