1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-06-10 19:37:31 +02:00
comprehensive-rust/src/iterators/intoiterator.md

85 lines
2.1 KiB
Markdown
Raw Normal View History

---
minutes: 5
---
# `IntoIterator`
The `Iterator` trait tells you how to _iterate_ once you have created an
iterator. The related trait
[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html)
defines how to create an iterator for a type. It is used automatically by the
`for` loop.
```rust,editable
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)> {
self.i += 1;
if self.i >= self.grid.x_coords.len() {
self.i = 0;
self.j += 1;
if self.j >= self.grid.y_coords.len() {
return None;
}
}
Some((self.grid.x_coords[self.i], self.grid.y_coords[self.j]))
}
}
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}");
}
}
```
<details>
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`: the `Iterator` type returned by the `into_iter` method.
Note that `IntoIter` and `Item` are linked: the iterator must have the same
`Item` type, which means that it returns `Option<Item>`
The example iterates over all combinations of x and y coordinates.
Try iterating over the grid twice in `main`. Why does this fail? Note that
`IntoIterator::into_iter` takes ownership of `self`.
Fix this issue by implementing `IntoIterator` for `&Grid` and storing a
reference to the `Grid` in `GridIter`.
The same problem can occur for standard library types: `for e in some_vector`
will take ownership of `some_vector` and iterate over owned elements from that
vector. Use `for e in &some_vector` instead, to iterate over references to
elements of `some_vector`.
</details>