Итераторы
Трейт 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);
}
}