Ricerca…
Sintassi
loop { block } // infinito loop
while condition { block }
mentre lascia pattern = expr { block }
per il modello in expr { block } // expr deve implementare IntoIterator
continua // salta alla fine del corpo del ciclo, iniziando una nuova iterazione, se necessario
pausa // interrompi il ciclo
' label : loop { block }
' label : while condition { block }
' label : while let pattern = expr { block }
' label : per pattern in expr { block }
continua ' label // salta alla fine dell'etichetta etichettata con il corpo del loop, avviando una nuova iterazione, se necessario
break ' label // interrompe l'etichetta etichettata loop
Nozioni di base
Ci sono 4 costrutti di looping in Rust. Tutti gli esempi di seguito producono lo stesso risultato.
Cicli infiniti
let mut x = 0;
loop {
if x > 3 { break; }
println!("{}", x);
x += 1;
}
Mentre cicli
let mut x = 0;
while x <= 3 {
println!("{}", x);
x += 1;
}
Vedi anche: Qual è la differenza tra loop
e while true
?
Cicli combinati con schema
Questi sono a volte noti come while let
cicli per brevità.
let mut x = Some(0);
while let Some(v) = x {
println!("{}", v);
x = if v < 3 { Some(v + 1) }
else { None };
}
Questo è equivalente a una match
all'interno di un blocco di loop
:
let mut x = Some(0);
loop {
match x {
Some(v) => {
println!("{}", v);
x = if v < 3 { Some(v + 1) }
else { None };
}
_ => break,
}
}
Per loop
In Rust, for
loop può essere utilizzato solo con un oggetto "iterable" (cioè dovrebbe implementare IntoIterator
).
for x in 0..4 {
println!("{}", x);
}
Questo è equivalente al seguente snippet che coinvolge while let
:
let mut iter = (0..4).into_iter();
while let Some(v) = iter.next() {
println!("{}", v);
}
Nota: 0..4
restituisce un oggetto Range
che implementa già il tratto Iterator
. Pertanto into_iter()
non è necessaria, ma è tenuto solo per illustrare ciò che for
fa. Per un approfondimento, vedi la documentazione ufficiale for
Loops e IntoIterator
.
Vedi anche: Iterators
Maggiori informazioni sui loop For
Come accennato in Nozioni di base, possiamo usare tutto ciò che implementa IntoIterator
con il ciclo for
:
let vector = vec!["foo", "bar", "baz"]; // vectors implement IntoIterator
for val in vector {
println!("{}", val);
}
Uscita prevista:
foo
bar
baz
Si noti che l'iterazione sul vector
in questo modo la consuma (dopo il ciclo for
, il vector
non può essere riutilizzato). Questo perché IntoIterator::into_iter
sposta self
.
IntoIterator
è anche implementato da &Vec<T>
e &mut Vec<T>
(producendo valori con tipi &T
e &mut T
rispettivamente) in modo da poter impedire lo spostamento del vector
semplicemente passandolo per riferimento:
let vector = vec!["foo", "bar", "baz"];
for val in &vector {
println!("{}", val);
}
println!("{:?}", vector);
Si noti che val
è di tipo &&str
, poiché vector
è di tipo Vec<&str>
.
Controllo del ciclo
Tutti i costrutti di ciclo consentono l'uso di istruzioni break
e continue
. Influiscono sul ciclo immediatamente circostante (più interno).
Basic Loop Control
break
termina il ciclo:
for x in 0..5 {
if x > 2 { break; }
println!("{}", x);
}
Produzione 0
1
2
continue
termina l'iterazione corrente in anticipo
for x in 0..5 {
if x < 2 { continue; }
println!("{}", x);
}
Produzione 2
3
4
Controllo avanzato del ciclo
Ora, supponiamo di avere cicli annidati e vogliamo break
verso il ciclo esterno. Quindi, possiamo usare le etichette di loop per specificare a quale ciclo si applica una break
o continue
. Nell'esempio seguente, 'outer
è l'etichetta data al loop esterno.
'outer: for i in 0..4 {
for j in i..i+2 {
println!("{} {}", i, j);
if i > 1 {
continue 'outer;
}
}
println!("--");
}
Produzione 0 0
0 1
--
1 1
1 2
--
2 2
3 3
Per i > 1
, il ciclo interno è stato iterato una sola volta e --
non è stato stampato.
Nota: non confondere un'etichetta di loop con una variabile a vita. Le variabili a vita si verificano solo accanto a un &
o come parametro generico all'interno di <>
.