Поиск…
Синтаксис
loop { block } // бесконечный цикл
а условие { block }
а пусть pattern = expr { block }
для шаблона в expr { block } // expr должен реализовать IntoIterator
continue // перейти к концу тела цикла, при необходимости начать новую итерацию
break // остановить цикл
' label : loop { block }
' label : while условие { block }
' label : while let pattern = expr { block }
' label : для шаблона в expr { block }
продолжить 'метки // переход к концу меченой этикетки тела цикла, начиная с новой итерацией в случае необходимости
метка BREAK '// остановить метку цикла меченого
основы
В Rust есть 4 петлевые конструкции. Все приведенные ниже примеры дают одинаковый результат.
Бесконечные петли
let mut x = 0;
loop {
if x > 3 { break; }
println!("{}", x);
x += 1;
}
В то время как петли
let mut x = 0;
while x <= 3 {
println!("{}", x);
x += 1;
}
Также смотрите: В чем разница между loop
и while true
?
Циклы, совпадающие с шаблонами
Они иногда известны как while let
петлям для краткости.
let mut x = Some(0);
while let Some(v) = x {
println!("{}", v);
x = if v < 3 { Some(v + 1) }
else { None };
}
Это эквивалентно match
внутри блока loop
:
let mut x = Some(0);
loop {
match x {
Some(v) => {
println!("{}", v);
x = if v < 3 { Some(v + 1) }
else { None };
}
_ => break,
}
}
Для циклов
В Rust for
цикла может использоваться только с «итерируемым» объектом (т.е. он должен реализовывать IntoIterator
).
for x in 0..4 {
println!("{}", x);
}
Это эквивалентно следующему фрагменту, включая while let
:
let mut iter = (0..4).into_iter();
while let Some(v) = iter.next() {
println!("{}", v);
}
Примечание: 0..4
возвращает объект Range
который уже реализует свойство Iterator
. Поэтому into_iter()
не является необходимым, но сохраняется только для иллюстрации того, что for
делает. IntoIterator
обзор см. В официальных документах for
циклов и IntoIterator
.
См. Также: Итераторы
Подробнее о циклах
Как уже упоминалось в «Основах», мы можем использовать все, что реализует IntoIterator
с циклом for
:
let vector = vec!["foo", "bar", "baz"]; // vectors implement IntoIterator
for val in vector {
println!("{}", val);
}
Ожидаемый результат:
foo
bar
baz
Обратите внимание, что итерация по vector
таким образом потребляет его (после цикла for
vector
не может использоваться снова). Это связано с тем, что IntoIterator::into_iter
движется self
.
IntoIterator
также реализуется с помощью &Vec<T>
и &mut Vec<T>
(выводя значения с типами &T
и &mut T
соответственно), поэтому вы можете предотвратить перемещение vector
, просто передав его по ссылке:
let vector = vec!["foo", "bar", "baz"];
for val in &vector {
println!("{}", val);
}
println!("{:?}", vector);
Заметим, что val
имеет тип &&str
, так как vector
имеет тип Vec<&str>
.
Управление петлей
Все петлевые конструкции позволяют использовать выражения break
и continue
. Они воздействуют на ближайшую окружную (самую внутреннюю) петлю.
Управление базовым контуром
break
завершает цикл:
for x in 0..5 {
if x > 2 { break; }
println!("{}", x);
}
Выход 0
1
2
continue
завершение текущей итерации раньше
for x in 0..5 {
if x < 2 { continue; }
println!("{}", x);
}
Выход 2
3
4
Управление расширенным контуром
Теперь предположим, что у нас есть вложенные петли и мы хотим break
во внешний цикл. Затем мы можем использовать метки меток, чтобы указать, к какому циклу относится break
или continue
. В следующем примере 'outer
- это метка, присвоенная внешнему циклу.
'outer: for i in 0..4 {
for j in i..i+2 {
println!("{} {}", i, j);
if i > 1 {
continue 'outer;
}
}
println!("--");
}
Выход 0 0
0 1
--
1 1
1 2
--
2 2
3 3
При i > 1
внутренний цикл повторялся только один раз и --
не печатался.
Примечание. Не путайте метку цикла с переменной времени жизни. Постоянные переменные встречаются только рядом с &
или как общий параметр внутри <>
.