// Example 085: Iterator Trait
// OCaml Seq โ Rust Iterator
// === Approach 1: Implementing Iterator for a custom type ===
struct Range {
current: i32,
end_: i32,
}
impl Range {
fn new(start: i32, end_: i32) -> Self {
Range { current: start, end_ }
}
}
impl Iterator for Range {
type Item = i32;
fn next(&mut self) -> Option<Self::Item> {
if self.current >= self.end_ {
None
} else {
let val = self.current;
self.current += 1;
Some(val)
}
}
}
// === Approach 2: Iterator with map/filter (free from trait) ===
struct Counter {
current: u64,
}
impl Counter {
fn from(start: u64) -> Self {
Counter { current: start }
}
}
impl Iterator for Counter {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
let val = self.current;
self.current += 1;
Some(val) // infinite!
}
}
// === Approach 3: Iterator via IntoIterator ===
struct Repeat<T: Clone> {
value: T,
remaining: usize,
}
impl<T: Clone> Repeat<T> {
fn new(value: T, count: usize) -> Self {
Repeat { value, remaining: count }
}
}
impl<T: Clone> Iterator for Repeat<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.remaining == 0 {
None
} else {
self.remaining -= 1;
Some(self.value.clone())
}
}
}
// Generic function working with any iterator
fn sum_first_n<I: Iterator<Item = i32>>(iter: I, n: usize) -> i32 {
iter.take(n).sum()
}
fn collect_mapped<I, F, B>(iter: I, f: F) -> Vec<B>
where
I: Iterator,
F: Fn(I::Item) -> B,
{
iter.map(f).collect()
}
fn main() {
// Custom Range iterator
let range = Range::new(1, 6);
let nums: Vec<i32> = range.collect();
println!("Range: {:?}", nums);
// Map and filter come free
let doubled: Vec<i32> = Range::new(1, 6).map(|x| x * 2).collect();
println!("Doubled: {:?}", doubled);
let evens: Vec<i32> = Range::new(1, 11).filter(|x| x % 2 == 0).collect();
println!("Evens: {:?}", evens);
// Infinite counter with take
let first5: Vec<u64> = Counter::from(0).take(5).collect();
println!("First 5: {:?}", first5);
// Chained
let result: Vec<u64> = Counter::from(1)
.map(|x| x * x)
.filter(|x| x % 2 == 1)
.take(5)
.collect();
println!("Odd squares: {:?}", result);
// Repeat
let hellos: Vec<&str> = Repeat::new("hello", 3).collect();
println!("Repeats: {:?}", hellos);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_range() {
let v: Vec<i32> = Range::new(1, 6).collect();
assert_eq!(v, vec![1, 2, 3, 4, 5]);
}
#[test]
fn test_empty_range() {
let v: Vec<i32> = Range::new(5, 5).collect();
assert!(v.is_empty());
}
#[test]
fn test_range_map() {
let v: Vec<i32> = Range::new(1, 4).map(|x| x * 10).collect();
assert_eq!(v, vec![10, 20, 30]);
}
#[test]
fn test_range_filter() {
let v: Vec<i32> = Range::new(1, 11).filter(|x| x % 3 == 0).collect();
assert_eq!(v, vec![3, 6, 9]);
}
#[test]
fn test_counter_take() {
let v: Vec<u64> = Counter::from(10).take(3).collect();
assert_eq!(v, vec![10, 11, 12]);
}
#[test]
fn test_counter_chain() {
let sum: u64 = Counter::from(1).take(100).sum();
assert_eq!(sum, 5050);
}
#[test]
fn test_repeat() {
let v: Vec<i32> = Repeat::new(42, 4).collect();
assert_eq!(v, vec![42, 42, 42, 42]);
}
#[test]
fn test_sum_first_n() {
let sum = sum_first_n(Range::new(1, 100), 10);
assert_eq!(sum, 55);
}
#[test]
fn test_collect_mapped() {
let v = collect_mapped(Range::new(1, 4), |x| x.to_string());
assert_eq!(v, vec!["1", "2", "3"]);
}
}
(* Example 085: Iterator Trait *)
(* OCaml Seq โ Rust Iterator *)
(* Approach 1: Using Seq (lazy sequences) *)
let range start stop =
let rec aux n () =
if n >= stop then Seq.Nil
else Seq.Cons (n, aux (n + 1))
in
aux start
let seq_to_list seq =
Seq.fold_left (fun acc x -> x :: acc) [] seq |> List.rev
(* Approach 2: Custom iterator via closure *)
type 'a iterator = {
next : unit -> 'a option;
}
let range_iter start stop =
let current = ref start in
{ next = fun () ->
if !current >= stop then None
else begin
let v = !current in
incr current;
Some v
end
}
let iter_to_list it =
let rec aux acc =
match it.next () with
| None -> List.rev acc
| Some v -> aux (v :: acc)
in
aux []
let iter_map f it =
{ next = fun () ->
match it.next () with
| None -> None
| Some v -> Some (f v)
}
let iter_filter pred it =
let rec find () =
match it.next () with
| None -> None
| Some v -> if pred v then Some v else find ()
in
{ next = find }
(* Approach 3: Using List as iterator source *)
let counter_from n =
let c = ref n in
{ next = fun () ->
let v = !c in
c := v + 1;
Some v
}
let take n it =
let count = ref 0 in
{ next = fun () ->
if !count >= n then None
else begin
incr count;
it.next ()
end
}
(* Tests *)
let () =
let s = range 1 6 in
assert (seq_to_list s = [1; 2; 3; 4; 5]);
let it = range_iter 1 6 in
assert (iter_to_list it = [1; 2; 3; 4; 5]);
let it2 = range_iter 1 11 in
let doubled = iter_map (fun x -> x * 2) it2 in
let evens = iter_filter (fun x -> x <= 10) doubled in
assert (iter_to_list evens = [2; 4; 6; 8; 10]);
let inf = counter_from 0 in
let first5 = take 5 inf in
assert (iter_to_list first5 = [0; 1; 2; 3; 4]);
Printf.printf "โ All tests passed\n"