Цикл по коллекции с помощью for
Вы можете выбрать использовать конструкцию while
для перебора элементов коллекции, такой как массив. Например, цикл в Listing 3-4 выводит каждый элемент массива a
.
Имя файла: src/main.rs
fn main() {
let a = [10, 20, 30, 40, 50];
let mut index = 0;
while index < 5 {
println!("the value is: {}", a[index]);
index += 1;
}
}
Listing 3-4: Цикл по каждому элементу коллекции с использованием цикла while
Здесь код перебирает элементы массива в порядке возрастания. Он начинается с индекса 0
, а затем цикл продолжается, пока не достигнет последнего индекса в массиве (то есть, когда index < 5
перестает быть истинным). Запуск этого кода выведет каждый элемент массива:
$ cargo run
Compiling loops v0.1.0 (file:///projects/loops)
Finished dev [unoptimized + debuginfo] target(s) in 0.32s
Running `target/debug/loops`
the value is: 10
the value is: 20
the value is: 30
the value is: 40
the value is: 50
Все пять значений массива появляются в терминале, как ожидается. Даже если index
в какой-то момент достигнет значения 5
, цикл остановится перед попыткой получить шестое значение из массива.
Однако этот подход подвержен ошибкам; мы можем привести программу к панике, если значение индекса или условие проверки будет неверным. Например, если вы измените определение массива a
на четыре элемента, но забыете обновить условие до while index < 4
, код будет приводить к панике. Кроме того, этот подход медленный, потому что компилятор добавляет код времени выполнения для выполнения условной проверки того, находится ли индекс внутри границ массива на каждой итерации цикла.
В качестве более компактного альтернативы вы можете использовать цикл for
и выполнить некоторый код для каждого элемента в коллекции. Цикл for
выглядит как код в Listing 3-5.
Имя файла: src/main.rs
fn main() {
let a = [10, 20, 30, 40, 50];
for element in a {
println!("the value is: {element}");
}
}
Listing 3-5: Цикл по каждому элементу коллекции с использованием цикла for
Когда мы запускаем этот код, мы увидим такой же вывод, как в Listing 3-4. Более важно, мы повысили безопасность кода и избавились от возможных ошибок, которые могли возникнуть из-за выхода за пределы массива или не полного перебора элементов.
При использовании цикла for
вам не нужно запоминать изменять какой-либо другой код, если вы измените количество значений в массиве, в отличие от метода, использованного в Listing 3-4.
Безопасность и компактность циклов for
делают их наиболее часто используемой конструкцией цикла в Rust. Даже в ситуациях, когда вы хотите выполнить некоторый код определенное количество раз, как в примере с обратным отсчетом, который использовал цикл while
в Listing 3-3, большинство Rustaceans предпочтут использовать цикл for
. Способ сделать это - использовать Range
, предоставляемый стандартной библиотекой, который генерирует все числа последовательно, начиная с одного числа и заканчивая перед другим числом.
Вот, как бы выглядел обратный отсчет с использованием цикла for
и другого метода, о котором мы еще не говорили, rev
, чтобы перевернуть диапазон:
Имя файла: src/main.rs
fn main() {
for number in (1..4).rev() {
println!("{number}!");
}
println!("LIFTOFF!!!");
}
Этот код выглядит лучше, не так ли?