IntoIterator
ویژگی Iterator به شما میگوید که چگونه پس از ایجاد یک تکرار کننده، iterate کنید. ویژگی مرتبط IntoIterator نحوه ایجاد یک تکرار کننده برای یک نوع را مشخص میکند. به طور خودکار توسط حلقه 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}"); } }
روی مستنداتIntoIterator کلیک کنید. هر پیادهسازی IntoIterator باید دو نوع را اعلام کند:
- ء
Item: نوعی که باید تکرار شود، مانندi8، IntoIter: یک «Iterator» تایپ است که با متدinto_iterبرگردانده شده است.
توجه داشته باشید که IntoIter وItem به هم link شدهاند: تکرارکننده (iterator) باید همان Item type را داشته باشد، به این معنی که Option<Item> را برمیگرداند.
مثال روی تمام ترکیبات مختصات x و y تکرار میشود.
سعی کنید دو بار روی شبکه در main تکرار کنید. چرا این گزینه شکست میخورد؟ توجه داشته باشید که IntoIterator::into_iter مالکیت self را میگیرد.
این مشکل را با اجرای IntoIterator برای &Grid و ذخیره یک reference به این Grid در GridIter برطرف کنید.
همین مشکل میتواند برای انواع کتابخانه استاندارد رخ دهد: برای e در some_vector مالکیت some_vector را در اختیار میگیرد و روی عناصر متعلق به آن بردار تکرار میشود. به جای آن از e در &some_vector برای تکرار بر روی ارجاعات به عناصر some_vector استفاده کنید.