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

Трейт Iterator говорит, как итерироваться, когда итератор уже создан. Связанный трейт IntoIterator определяет, как создать итератор для типа. Он используется автоматически циклом for.

// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0

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}");
    }

    // dbg!(&grid.x_coords); // ❌ Сетка была потреблена циклом.
}
This slide should take about 5 minutes.
  • IntoIterator — трейт, благодаря которому работают циклы for. Его реализуют типы коллекций, например Vec<T>, и ссылки на них, например &Vec<T> и &[T]. Его также реализуют диапазоны. Поэтому можно перебирать вектор через for i in some_vec { .. }, но метода some_vec.next() не существует.

Перейдите по ссылке на документацию IntoIterator. Каждая реализация IntoIterator должна объявлять два типа:

  • Item: тип элементов, по которым идёт итерация, например i8,
  • IntoIter: тип Iterator, который возвращает метод into_iter.

Обратите внимание, что IntoIter и Item связаны: итератор должен иметь тот же тип Item, а значит, возвращать Option<Item>.

Пример перебирает все комбинации координат x и y.

Раскомментируйте закомментированную строку в main и покажите ошибку компилятора. Обратите внимание, что IntoIterator::into_iter забирает владение self. На следующем слайде показано, как этого избежать, перебирая &Grid через дополнительную реализацию IntoIterator.