Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

IntoIterator

The Iterator trait tells you how to iterate once you have created an iterator. The related trait IntoIterator defines how to create an iterator for a type. It is used automatically by the for loop.

struct Grid {
    x_coords: Vec<u32>,
    y_coords: Vec<u32>,
}

impl IntoIterator for Grid {
    type Item = (u32, u32);
    type IntoIter = GridIter;
    fn into_iter(self) -> GridIter {
        GridIter { grid: self, i: 0, j: 0 }
    }
}

struct GridIter {
    grid: Grid,
    i: usize,
    j: usize,
}

impl Iterator for GridIter {
    type Item = (u32, u32);

    fn next(&mut self) -> Option<(u32, u32)> {
        if self.i >= self.grid.x_coords.len() {
            self.i = 0;
            self.j += 1;
            if self.j >= self.grid.y_coords.len() {
                return None;
            }
        }
        let res = Some((self.grid.x_coords[self.i], self.grid.y_coords[self.j]));
        self.i += 1;
        res
    }
}

fn main() {
    let grid = Grid { x_coords: vec![3, 5, 7, 9], y_coords: vec![10, 20, 30, 40] };
    for (x, y) in grid {
        println!("point = {x}, {y}");
    }
}
This slide should take about 5 minutes.

Click through to the docs for IntoIterator. Every implementation of IntoIterator must declare two types:

  • Item: the type to iterate over, such as i8,
  • IntoIterinto_iter 方法傳回的 Iterator 型別。

請注意,IntoIterItem 已建立連結:疊代器必須具有相同的 Item 型別,表示會傳回 Option<Item>

此範例會對 x 和 y 座標的所有組合進行疊代。

請嘗試在 main 中對格線疊代兩次。想想為什麼這樣會失敗?請注意,IntoIterator::into_iter 會取得 self 的擁有權。

如要修正此問題,請針對 &Grid 實作 IntoIterator,並將 Grid 的參照儲存在 GridIter 中。

標準程式庫型別可能會發生同樣的問題,也就是 for e in some_vector 會取得 some_vector 的擁有權,並對該向量內擁有的元素進行疊代。因此,請改用 for e in &some_vector 疊代處理對 some_vector 元素的參照。