Итераторы
Итератор отвечает за логику перебора элементов и определение момента завершения последовательности.
В Rust итераторы ленивые (lazy), то есть они не делают ничего, пока вы не вызовете специальные методы, потребляющие итератор, чтобы задействовать его.
Итератор это просто счетчик со ссылкой на объект со значениями
#![allow(unused)] fn main() { let v1 = vec![1, 2, 3]; let v1_iter = v1.iter(); for val in v1_iter { println!("Got: {val}"); } }
Типаж Iterator и метод next
#![allow(unused)] fn main() { pub trait Iterator { type Item; fn next(&mut self) -> Option<Self::Item>; // methods with default implementations elided } }
Если мы хотим создать итератор, который становится владельцем
v1и возвращает принадлежащие ему значения, мы можем вызватьinto_iterвместоiter. Точно так же, если мы хотим перебирать изменяемые ссылки, мы можем вызватьiter_mutвместоiter.
#![allow(unused)] fn main() { let v2_iter = v1.iter(); let total: i32 = v2_iter.sum(); println!("{}",total); }
это тоже работает
Методы, которые создают другие итераторы
Адаптеры итераторов - это методы, определённые для трейта Iterator, которые не потребляют итератор. Вместо этого они создают различные итераторы, изменяя некоторые аспекты исходного итератора.
Итератор нужно обязательно потребить или будут ошибка
Создает новый итератор:
#![allow(unused)] fn main() { let v1: Vec<i32> = vec![1, 2, 3]; v1.iter().map(|x| x + 1); }
filter
#![allow(unused)] fn main() { #[derive(PartialEq, Debug)] struct Shoe { size: u32, style: String, } fn shoes_in_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> { //получает на вход вектор и захватывает его -> возвращает вектор удовлетворяющий условию shoes.into_iter().filter(|s| s.size == shoe_size).collect() //собирает коллекцию с помощью фильтра } }
Коррекция листинга приложения
#![allow(unused)] fn main() { let config = Config::build(env::args()).unwrap_or_else(|err| { eprintln!("Problem parsing arguments: {err}"); process::exit(1); }); //env::args() — возвращает итератор И не нужно создавать вектор }
и поменяем вызов функции
#![allow(unused)] fn main() { impl Config { fn build( mut args: impl Iterator<Item = String>, ) -> Result<Config, &'static str> { // --snip-- }