Реализация итераторов в Rust

RustRustBeginner
Практиковаться сейчас

This tutorial is from open-source community. Access the source code

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этом лабе мы узнаем о трейте Iterator в Rust, который используется для реализации итераторов над коллекциями, такими как массивы. Трейт Iterator требует определения метода next для итератора и может быть реализован вручную в блоке impl или автоматически определен для массивов и диапазонов. Конструкция for может быть использована для удобного преобразования некоторых коллекций в итераторы с использованием метода .into_iter(). Лаб предоставляет пример реализации генератора последовательности Фибоначчи в виде итератора, демонстрируя, как определить метод next и использовать трейт Iterator. Кроме того, показано использование методов take и skip для управления итераторами, а также метода iter для итерации по массивам.

Примечание: Если в лабе не указано имя файла, вы можете использовать любое имя файла, которое хотите. Например, вы можете использовать main.rs, скомпилировать и запустить его с помощью rustc main.rs &&./main.

Итераторы

Трейт Iterator используется для реализации итераторов над коллекциями, такими как массивы.

Трейт требует определения только метода для следующего (next) элемента, который может быть определен вручную в блоке impl или автоматически (как в массивах и диапазонах).

В качестве удобства для общих случаев конструкция for преобразует некоторые коллекции в итераторы с использованием метода .into_iter().

struct Fibonacci {
    curr: u32,
    next: u32,
}

// Реализуем `Iterator` для `Fibonacci`.
// Трейт `Iterator` требует определения только метода для следующего (`next`) элемента.
impl Iterator for Fibonacci {
    // Мы можем ссылаться на этот тип с использованием Self::Item
    type Item = u32;

    // Здесь мы определяем последовательность с использованием `.curr` и `.next`.
    // Тип возврата - `Option<T>`:
    //     * Когда итератор завершен, возвращается `None`.
    //     * В противном случае следующее значение оборачивается в `Some` и возвращается.
    // Мы используем Self::Item в типе возврата, чтобы можно было изменить
    // тип без необходимости обновления сигнатур функций.
    fn next(&mut self) -> Option<Self::Item> {
        let current = self.curr;

        self.curr = self.next;
        self.next = current + self.next;

        // Поскольку у последовательности Фибоначчи нет конечной точки, итератор
        // никогда не вернет `None`, и всегда возвращается `Some`.
        Some(current)
    }
}

// Возвращает генератор последовательности Фибоначчи
fn fibonacci() -> Fibonacci {
    Fibonacci { curr: 0, next: 1 }
}

fn main() {
    // `0..3` - это итератор, который генерирует: 0, 1 и 2.
    let mut sequence = 0..3;

    println!("Четыре последовательных вызова `next` для 0..3");
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());

    // `for` работает с итератором до тех пор, пока он не вернет `None`.
    // Каждое значение `Some` извлекается и связывается с переменной (здесь, `i`).
    println!("Итерируемся по 0..3 с использованием `for`");
    for i in 0..3 {
        println!("> {}", i);
    }

    // Метод `take(n)` сокращает итератор до первых `n` элементов.
    println!("Первые четыре элемента последовательности Фибоначчи: ");
    for i in fibonacci().take(4) {
        println!("> {}", i);
    }

    // Метод `skip(n)` сокращает итератор, отбрасывая первые `n` элементов.
    println!("Следующие четыре элемента последовательности Фибоначчи: ");
    for i in fibonacci().skip(4).take(4) {
        println!("> {}", i);
    }

    let array = [1u32, 3, 3, 7];

    // Метод `iter` создает итератор для массива/слайса.
    println!("Итерируем следующий массив {:?}", &array);
    for i in array.iter() {
        println!("> {}", i);
    }
}

Резюме

Поздравляем! Вы завершили лабу по Итераторам. Вы можете практиковаться в других лабах в LabEx, чтобы улучшить свои навыки.