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}");
}
}
Click through to the docs for IntoIterator. Every implementation of IntoIterator must declare two types:
Item: the type to iterate over, such asi8,IntoIter:into_iter方法傳回的Iterator型別。
請注意,IntoIter 和 Item 已建立連結:疊代器必須具有相同的 Item 型別,表示會傳回 Option<Item>。
此範例會對 x 和 y 座標的所有組合進行疊代。
請嘗試在 main 中對格線疊代兩次。想想為什麼這樣會失敗?請注意,IntoIterator::into_iter 會取得 self 的擁有權。
如要修正此問題,請針對 &Grid 實作 IntoIterator,並將 Grid 的參照儲存在 GridIter 中。
標準程式庫型別可能會發生同樣的問題,也就是 for e in some_vector 會取得 some_vector 的擁有權,並對該向量內擁有的元素進行疊代。因此,請改用 for e in &some_vector 疊代處理對 some_vector 元素的參照。