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}"); } }
Clique na documentação para IntoIterator
. Toda implementação de IntoIterator
deve declarar dois tipos:
Item
: o tipo sobre o qual iteramos, comoi8
,IntoIter
: o tipoIterator
retornado pelo métodointo_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
.