Day 4:自訂迭代器

學習目標

  • 實作 Iterator trait
  • 理解 associated type Item
  • 自己做出一個迭代器型別

今日重點

Iterator trait

pub trait Iterator {
    type Item;                                    // 產出元素的型別
    fn next(&mut self) -> Option<Self::Item>;     // 唯一必實作的方法
    // 其他方法(map、filter 等)都是從 next 推導的預設實作
}

自訂迭代器

struct Counter {
    count: u32,
    max: u32,
}

impl Counter {
    fn new(max: u32) -> Counter {
        Counter { count: 0, max }
    }
}

impl Iterator for Counter {
    type Item = u32;

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

fn main() {
    let counter = Counter::new(5);
    let v: Vec<_> = counter.collect();   // [1, 2, 3, 4, 5]
    println!("{:?}", v);
}

有了 Iterator,自動獲得一堆方法

一實作 next,就免費拿到 .sum().map().filter().fold().collect() 等眾多方法,因為它們都以 next 為基礎實作。

練習

struct Fibonacci {
    a: u64,
    b: u64,
}

impl Fibonacci {
    fn new() -> Fibonacci { Fibonacci { a: 0, b: 1 } }
}

impl Iterator for Fibonacci {
    type Item = u64;
    fn next(&mut self) -> Option<Self::Item> {
        let current = self.a;
        let next = self.a + self.b;
        self.a = self.b;
        self.b = next;
        Some(current)   // 0, 1, 1, 2, 3, 5...
    }
}

// 1. 用 take(10) 取前 10 個費式數
// 2. 用 sum() 加總前 10 個

自我檢查

  • 理解 type Item 與 next()
  • 能自訂迭代器型別
  • 知道實作 Iterator 後會自動獲得大量方法
  • 會用 take / skip 等適配器

深入連結

  • The Book 第 13 章「Creating Your Own Iterators with the Iterator Trait」