Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Трейт Iterator

Трейт Iterator определяет, как объект можно использовать для получения последовательности значений. Например, если мы хотим создать итератор, который выдаёт элементы среза, это может выглядеть примерно так:

// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0

struct SliceIter<'s> {
    slice: &'s [i32],
    i: usize,
}

impl<'s> Iterator for SliceIter<'s> {
    type Item = &'s i32;

    fn next(&mut self) -> Option<Self::Item> {
        if self.i == self.slice.len() {
            None
        } else {
            let next = &self.slice[self.i];
            self.i += 1;
            Some(next)
        }
    }
}

fn main() {
    let slice = &[2, 4, 6, 8];
    let iter = SliceIter { slice, i: 0 };
    for elem in iter {
        dbg!(elem);
    }
}
This slide should take about 5 minutes.
  • Пример SliceIter реализует ту же логику, что и цикл for в стиле C из предыдущего слайда.

  • Укажите студентам, что итераторы ленивы: создание итератора лишь инициализирует структуру, а никакой работы не выполняет. Работа начинается только при вызове метода next.

  • Итераторы не обязаны быть конечными! Вполне допустим итератор, который будет выдавать значения бесконечно. Например, полуоткрытый диапазон вроде 0.. будет продолжаться, пока не произойдёт переполнение целого.

Для дальнейшего изучения

  • «Настоящая» версия SliceIter — это тип slice::Iter из стандартной библиотеки, но настоящая версия использует под капотом указатели вместо индекса, чтобы исключить проверки границ.

  • Пример SliceIter хорошо показывает структуру, которая содержит ссылку, и поэтому использует аннотации времён жизни.

  • Также можно показать, как добавить обобщённый параметр в SliceIter, чтобы он работал с любым срезом (а не только с &[i32]).