Введение
В этом лабе мы узнаем о трейте 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, чтобы улучшить свои навыки.