Sök…
Syntax
loop { block } // oändlig loop
medan villkor { block }
medan låt mönster = expr {blocket}
för mönster i expr { block } // expr måste implementera IntoIterator
fortsätt // hoppa till slutet av slingkroppen, starta en ny iteration om det behövs
bryta // stoppa slingan
' etikett : loop { block }
' etikett : medan villkor { block }
'Label: medan låt mönster = expr {blocket}
' etikett : för mönster i expr { block }
Fortsätt ' etikett // hoppa till slutet av etiketten med slingkroppen märkt och starta en ny iteration om det behövs
break ' etikett // stoppa loopen märkt etikett
Grunderna
Det finns fyra slingkonstruktioner i Rust. Alla exempel nedan ger samma utgång.
Oändliga öglor
let mut x = 0;
loop {
if x > 3 { break; }
println!("{}", x);
x += 1;
}
Medan Loops
let mut x = 0;
while x <= 3 {
println!("{}", x);
x += 1;
}
Se också: Vad är skillnaden mellan loop
och while true
?
Mönster-matchade medan loopar
Dessa är ibland kända som while let
slingor för korthet.
let mut x = Some(0);
while let Some(v) = x {
println!("{}", v);
x = if v < 3 { Some(v + 1) }
else { None };
}
Detta motsvarar en match
inne i ett loop
:
let mut x = Some(0);
loop {
match x {
Some(v) => {
println!("{}", v);
x = if v < 3 { Some(v + 1) }
else { None };
}
_ => break,
}
}
För öglor
I Rust kan for
loop endast användas med ett "iterable" objekt (dvs. det ska implementera IntoIterator
).
for x in 0..4 {
println!("{}", x);
}
Detta motsvarar följande utdrag som involverar while let
:
let mut iter = (0..4).into_iter();
while let Some(v) = iter.next() {
println!("{}", v);
}
Obs: 0..4
returnerar ett Range
objekt som redan implementerar Iterator
drag . Därför är into_iter()
onödigt, men behålls bara för att illustrera vad for
gör. För en fördjupad tittning, se de officiella dokumenten for
Loops and IntoIterator
.
Se även: Iteratorer
Mer om för öglor
Som nämnts i Basics kan vi använda allt som implementerar IntoIterator
med for
loop:
let vector = vec!["foo", "bar", "baz"]; // vectors implement IntoIterator
for val in vector {
println!("{}", val);
}
Förväntad produktion:
foo
bar
baz
Observera att iterering över vector
på detta sätt konsumerar den (efter for
loopen kan vector
inte användas igen). Detta beror på att IntoIterator::into_iter
rör sig self
.
IntoIterator
implementeras också av &Vec<T>
och &mut Vec<T>
(ger värden med respektive typer &T
och &mut T
) så att du kan förhindra flyttningen av vector
genom att helt enkelt skicka den genom referens:
let vector = vec!["foo", "bar", "baz"];
for val in &vector {
println!("{}", val);
}
println!("{:?}", vector);
Observera att val
är av typen &&str
, eftersom vector
är av typen Vec<&str>
.
Loop Control
Alla loopingkonstruktioner tillåter användning av break
och continue
. De påverkar den omedelbara omgivande (innersta) slingan.
Grundläggande slingkontroll
break
avslutar slingan:
for x in 0..5 {
if x > 2 { break; }
println!("{}", x);
}
Produktion 0
1
2
continue
slutför den aktuella iterationen tidigt
for x in 0..5 {
if x < 2 { continue; }
println!("{}", x);
}
Produktion 2
3
4
Avancerad slingkontroll
Anta nu att vi har kapslade öglor och vill break
ut till den yttre slingan. Sedan kan vi använda loopetiketter för att specificera vilken slinga en break
eller continue
gäller. I följande exempel är 'outer
etiketten som ges till den yttre slingan.
'outer: for i in 0..4 {
for j in i..i+2 {
println!("{} {}", i, j);
if i > 1 {
continue 'outer;
}
}
println!("--");
}
Produktion 0 0
0 1
--
1 1
1 2
--
2 2
3 3
För i > 1
upprepades den inre slingan bara en gång och --
trycktes inte.
Obs: Förväxla inte en loopetikett med en livstidsvariabel. Livstidsvariabler förekommer endast bredvid en &
eller som en generisk parameter inom <>
.