13.3 Creating Custom Iterators

Creating custom iterators allows you to tailor iteration to specific needs.

13.3.1 Defining a Custom Iterator Struct

Let's create a custom range iterator named MyRange.

#![allow(unused)]
fn main() {
struct MyRange {
    current: u32,
    end: u32,
}

impl MyRange {
    fn new(start: u32, end: u32) -> Self {
        MyRange { current: start, end }
    }
}
}

13.3.2 Implementing the Iterator Trait

Implement the Iterator trait by defining the next() method.

#![allow(unused)]
fn main() {
impl Iterator for MyRange {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current < self.end {
            let result = self.current;
            self.current += 1;
            Some(result)
        } else {
            None
        }
    }
}
}

13.3.3 Using Custom Iterators in for Loops

struct MyRange {
    current: u32,
    end: u32,
}
impl MyRange {
    fn new(start: u32, end: u32) -> Self {
        MyRange { current: start, end }
    }
}
impl Iterator for MyRange {
    type Item = u32;
    fn next(&mut self) -> Option<Self::Item> {
        if self.current < self.end {
            let result = self.current;
            self.current += 1;
            Some(result)
        } else {
            None
        }
    }
}
fn main() {
    let range = MyRange::new(10, 15);
    for number in range {
        print!("{} ", number);
    }
    // Output: 10 11 12 13 14
}

13.3.4 Building Complex Iterators

Example: Fibonacci Sequence Iterator

#![allow(unused)]
fn main() {
struct Fibonacci {
    current: u32,
    next: u32,
    max: u32,
}

impl Fibonacci {
    fn new(max: u32) -> Self {
        Fibonacci { current: 0, next: 1, max }
    }
}

impl Iterator for Fibonacci {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current > self.max {
            None
        } else {
            let new_next = self.current + self.next;
            let result = self.current;
            self.current = self.next;
            self.next = new_next;
            Some(result)
        }
    }
}
}

Using the Fibonacci Iterator:

struct Fibonacci {
    current: u32,
    next: u32,
    max: u32,
}
impl Fibonacci {
    fn new(max: u32) -> Self {
        Fibonacci { current: 0, next: 1, max }
    }
}
impl Iterator for Fibonacci {
    type Item = u32;
    fn next(&mut self) -> Option<Self::Item> {
        if self.current > self.max {
            None
        } else {
            let new_next = self.current + self.next;
            let result = self.current;
            self.current = self.next;
            self.next = new_next;
            Some(result)
        }
    }
}
fn main() {
    let fib = Fibonacci::new(21);
    for number in fib {
        print!("{} ", number);
    }
    // Output: 0 1 1 2 3 5 8 13 21
}