Цикл for
for и диапазоны
Конструкция for in может быть использована для итерации по итераторам (Iterator). Один из самых простых способов создать итератор это использовать диапазон значений a..b. Это вернёт нам значения от a (включительно) до b (исключительно) за один шаг.
Давайте напишем FizzBuzz, используя for вместо while.
fn main() { // `n` будет принимать значения: 1, 2, ..., 100 с каждой итерации for n in 1..101 { if n % 15 == 0 { println!("fizzbuzz"); } else if n % 3 == 0 { println!("fizz"); } else if n % 5 == 0 { println!("buzz"); } else { println!("{}", n); } } }
Также, может быть использован диапазон a..=b, включающий оба конца. Код выше может быть записан следующим образом:
fn main() { // `n` будет принимать значения: 1, 2, ..., 100 с каждой итерации for n in 1..=100 { if n % 15 == 0 { println!("fizzbuzz"); } else if n % 3 == 0 { println!("fizz"); } else if n % 5 == 0 { println!("buzz"); } else { println!("{}", n); } } }
for и итераторы
Конструкция for in может взаимодействовать с итератором разными способами. Как обсуждается далее про типаж Iterator, цикл for применяет к предоставленной коллекции метод into_iter, чтобы преобразовать её в итератор. Однако, это не единственный способ преобразования коллекции в итератор.
Каждый из методов into_iter, iter и iter_mut преобразует коллекцию в итератор по своему, предоставляя разные отображения содержащихся данных.
iter- эта функция заимствует каждый элемент коллекции на каждой итерации. Благодаря этому, он оставляет коллекцию нетронутой и доступной для использования после цикла.
fn main() { let names = vec!["Bob", "Frank", "Ferris"]; for name in names.iter() { match name { &"Ferris" => println!("Программисты Rust вокруг нас!"), _ => println!("Привет {}", name), } } }
into_iter- эта функция потребляет коллекцию так что на каждой итерации предоставляются данные. Коллекция больше не доступна для использования так как владение ею перешло в эту функцию.
fn main() { let names = vec!["Bob", "Frank", "Ferris"]; for name in names.into_iter() { match name { "Ferris" => println!("Программисты Rust вокруг нас!"), _ => println!("Привет {}", name), } } }
iter_mut- эта функция делает изменяемое заимствование каждого элемента коллекции, позволяя изменять коллекцию на месте.
fn main() { let mut names = vec!["Bob", "Frank", "Ferris"]; for name in names.iter_mut() { *name = match name { &mut "Ferris" => "Программисты Rust вокруг нас!", _ => "Привет", } } println!("имена: {:?}", names); }
В вышеуказанных кусках кода, обратите внимание на ветку match, которая имеет ключевое отличие в зависимости от типа выполнения итераций. Разница в типе, конечно, подразумевает различные действия, которые могут быть выполнены.