IntoIterator

O trait Iterator informa como iterar depois de criar um iterador. O trait relacionado IntoIterator define como criar um iterador para um tipo. Ele é usado automaticamente pelo laço for.

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.

Clique na documentação para IntoIterator. Toda implementação de IntoIterator deve declarar dois tipos:

  • Item: o tipo sobre o qual iteramos, como i8,
  • IntoIter: o tipo Iterator retornado pelo mĂ©todo into_iter.

Observe que IntoIter e Item estĂŁo vinculados: o iterador deve ter o mesmo tipo Item, o que significa que ele retorna Option<Item>

O exemplo itera sobre todas as combinaçÔes de coordenadas x e y.

Tente iterar sobre o grid duas vezes em main. Por que isso falha? Observe que IntoIterator::into_iter assume a propriedade de self.

Corrija este problema implementando IntoIterator para &Grid e armazenando uma referĂȘncia ao Grid em GridIter.

O mesmo problema pode ocorrer para tipos da biblioteca padrĂŁo: for e in some_vector assumirĂĄ a propriedade de some_vector e iterarĂĄ sobre elementos owned desse vetor. Use for e in &some_vector em vez disso, para iterar sobre referĂȘncias aos elementos de some_vector.