Цикл 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
, которая имеет ключевое отличие в зависимости от типа выполнения итераций. Разница в типе, конечно, подразумевает различные действия, которые могут быть выполнены.