Szukaj…
Składnia
loop { block } // nieskończona pętla
while condition { blok }
podczas gdy Let Pattern = expr { blok }
dla wzorca w wyraż { blok } // wyraż musi implementować IntoIterator
kontynuuj // przeskocz na koniec korpusu pętli, rozpoczynając w razie potrzeby nową iterację
break // zatrzymaj pętlę
' label : loop { block }
„ etykieta : while warunek { blok }
' label : while Let Pattern = expr { blok }
etykieta : dla wzorca w wyrażeniu { blok }
Kontynuuj ' etykieta // przeskocz na koniec etykiety oznaczonej jako treść pętli, rozpoczynając w razie potrzeby nową iterację
break ' label // zatrzymaj etykietę pętli
Podstawy
W Rust są 4 zapętlone konstrukcje. Wszystkie poniższe przykłady dają takie same wyniki.
Nieskończone pętle
let mut x = 0;
loop {
if x > 3 { break; }
println!("{}", x);
x += 1;
}
Podczas gdy pętle
let mut x = 0;
while x <= 3 {
println!("{}", x);
x += 1;
}
Zobacz także: Jaka jest różnica między loop
while true
?
Dopasowane do wzoru While Loops
Czasami są one znane jako pętle while let
dla zwięzłości.
let mut x = Some(0);
while let Some(v) = x {
println!("{}", v);
x = if v < 3 { Some(v + 1) }
else { None };
}
Jest to równoważne match
w bloku loop
:
let mut x = Some(0);
loop {
match x {
Some(v) => {
println!("{}", v);
x = if v < 3 { Some(v + 1) }
else { None };
}
_ => break,
}
}
Dla pętli
W przypadku Rust pętla for
może być używana tylko z „iterowalnym” obiektem (tzn. Powinna implementować IntoIterator
).
for x in 0..4 {
println!("{}", x);
}
Jest to równoważne z następującym fragmentem obejmującym while let
:
let mut iter = (0..4).into_iter();
while let Some(v) = iter.next() {
println!("{}", v);
}
Uwaga: 0..4
zwraca obiekt Range
który już implementuje cechę Iterator
. Dlatego into_iter()
nie jest konieczne, ale utrzymuje się tylko w celu zilustrowania tego, co for
nie. Dla dogłębnie, zobacz oficjalne dokumenty dotyczące for
pętli i IntoIterator
.
Zobacz także: Iteratory
Więcej informacji na temat pętli
Jak wspomniano w IntoIterator
, możemy użyć wszystkiego, co implementuje IntoIterator
z pętlą for
:
let vector = vec!["foo", "bar", "baz"]; // vectors implement IntoIterator
for val in vector {
println!("{}", val);
}
Oczekiwany wynik:
foo
bar
baz
Zauważ, że iteracja po vector
w ten sposób zużywa go (po pętli for
vector
nie może być ponownie użyty). To dlatego IntoIterator::into_iter
porusza self
.
IntoIterator
jest także implementowany przez &Vec<T>
i &mut Vec<T>
(uzyskując wartości odpowiednio z typami &T
i &mut T
), dzięki czemu można zapobiec przesunięciu vector
, po prostu przekazując go przez odniesienie:
let vector = vec!["foo", "bar", "baz"];
for val in &vector {
println!("{}", val);
}
println!("{:?}", vector);
Zauważ, że val
jest typu &&str
, ponieważ vector
jest typu Vec<&str>
.
Kontrola pętli
Wszystkie konstrukty przelotowe umożliwić korzystanie z break
i continue
oświadczenia. Wpływają na bezpośrednio otaczającą (wewnętrzną) pętlę.
Podstawowa kontrola pętli
break
kończy pętlę:
for x in 0..5 {
if x > 2 { break; }
println!("{}", x);
}
Wynik 0
1
2
continue
kończy bieżącą iterację
for x in 0..5 {
if x < 2 { continue; }
println!("{}", x);
}
Wynik 2
3
4
Zaawansowana kontrola pętli
Załóżmy teraz, że mamy zagnieżdżone pętle i chcemy break
się do zewnętrznej pętli. Następnie możemy użyć etykiet pętli, aby określić, do której pętli ma zastosowanie break
lub continue
. W poniższym przykładzie 'outer
jest etykietą nadaną zewnętrznej pętli.
'outer: for i in 0..4 {
for j in i..i+2 {
println!("{} {}", i, j);
if i > 1 {
continue 'outer;
}
}
println!("--");
}
Wynik 0 0
0 1
--
1 1
1 2
--
2 2
3 3
Dla i > 1
pętla wewnętrzna została iterowana tylko raz i --
nie została wydrukowana.
Uwaga: Nie należy mylić etykiety pętli ze zmienną dożywotnią. Zmienne dotyczące istnienia występują tylko obok &
lub jako parametr ogólny w <>
.