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,
  • “IntoIter”:“into_iter”方法返回的“Iterator”类型。

Note that IntoIter and Item are linked: the iterator must have the same Item type, which means that it returns Option<Item>

此示例对 x 坐标和 y 坐标的所有组合进行了迭代。

请尝试在 main 中对网格进行两次迭代。为什么会失败?请注意,IntoIterator::into_iter 获得了 self 的所有权。

如要解决此问题,请为 &Grid 实现 IntoIterator,并在 GridIter 中存储对 Grid 的引用。

对于标准库类型,可能会出现同样的问题:for e in some_vector 将获得 some_vector 的所有权,并迭代该矢量中的自有元素。请改用 for e in &some_vector 来迭代 some_vector 的元素的引用。