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
استفاده کنید.