Buscar..
Sintaxis
loop { bloque } // bucle infinito
condición { bloque }
mientras let patrón = expr { bloque }
para el patrón en expr { bloque } // expr debe implementar IntoIterator
continuar // saltar al final del cuerpo del bucle, comenzando una nueva iteración si es necesario
romper // detener el bucle
' label : loop { block }
' label : while condición { bloque }
' label : while let pattern = expr { block }
' label : para patrón en expr { bloque }
continue ' label // salta al final de la etiqueta etiquetada del cuerpo del bucle, iniciando una nueva iteración si es necesario
romper etiqueta // detener la etiqueta etiquetada en bucle
Lo esencial
Hay 4 construcciones en bucle en Rust. Todos los ejemplos a continuación producen el mismo resultado.
Bucles infinitos
let mut x = 0;
loop {
if x > 3 { break; }
println!("{}", x);
x += 1;
}
Mientras bucles
let mut x = 0;
while x <= 3 {
println!("{}", x);
x += 1;
}
También vea: ¿Cuál es la diferencia entre loop
y while true
?
Patrones combinados de patrones
Estos a veces se conocen como while let
bucles para la brevedad.
let mut x = Some(0);
while let Some(v) = x {
println!("{}", v);
x = if v < 3 { Some(v + 1) }
else { None };
}
Esto es equivalente a una match
dentro de un bloque de loop
:
let mut x = Some(0);
loop {
match x {
Some(v) => {
println!("{}", v);
x = if v < 3 { Some(v + 1) }
else { None };
}
_ => break,
}
}
Para loops
En Rust, for
loop solo se puede usar con un objeto "iterable" (es decir, debe implementar IntoIterator
).
for x in 0..4 {
println!("{}", x);
}
Esto es equivalente al siguiente fragmento de código while let
:
let mut iter = (0..4).into_iter();
while let Some(v) = iter.next() {
println!("{}", v);
}
Nota: 0..4
devuelve un objeto Range
que ya implementa el rasgo Iterator
. Por into_iter()
tanto, into_iter()
es necesario, pero se mantiene solo para ilustrar for
qué sirve. Para una mirada en profundidad, ver los documentos oficiales for
Loops y IntoIterator
.
Ver también: iteradores.
Más sobre For Loops
Como se mencionó en Conceptos básicos, podemos usar cualquier cosa que implemente IntoIterator
con el bucle for
:
let vector = vec!["foo", "bar", "baz"]; // vectors implement IntoIterator
for val in vector {
println!("{}", val);
}
Rendimiento esperado:
foo
bar
baz
Tenga en cuenta que la iteración sobre el vector
de esta manera lo consume (después del bucle for
, el vector
no se puede usar de nuevo). Esto se debe a que IntoIterator::into_iter
mueve a self
.
IntoIterator
también se implementa con &Vec<T>
y &mut Vec<T>
(obteniendo valores con los tipos &T
y &mut T
respectivamente) para que pueda evitar el movimiento del vector
simplemente pasándolo por referencia:
let vector = vec!["foo", "bar", "baz"];
for val in &vector {
println!("{}", val);
}
println!("{:?}", vector);
Tenga en cuenta que val
es de tipo &&str
, ya que vector
es de tipo Vec<&str>
.
Control de bucle
Todas las construcciones de bucle permiten el uso de las declaraciones break
y continue
. Afectan el bucle inmediato (más interno) que lo rodea.
Control de bucle básico
break
termina el bucle:
for x in 0..5 {
if x > 2 { break; }
println!("{}", x);
}
Salida 0
1
2
continue
termina la iteración actual temprano.
for x in 0..5 {
if x < 2 { continue; }
println!("{}", x);
}
Salida 2
3
4
Control de bucle avanzado
Ahora, supongamos que tenemos bucles anidados y queremos break
hacia el bucle externo. Luego, podemos usar etiquetas de bucle para especificar a qué bucle se aplica una break
o continue
. En el siguiente ejemplo, 'outer
es la etiqueta dada al bucle externo.
'outer: for i in 0..4 {
for j in i..i+2 {
println!("{} {}", i, j);
if i > 1 {
continue 'outer;
}
}
println!("--");
}
Salida 0 0
0 1
--
1 1
1 2
--
2 2
3 3
Para i > 1
, el bucle interno se itera sólo una vez y --
no se imprimió.
Nota: No confunda una etiqueta de bucle con una variable de por vida. Las variables de por vida solo aparecen junto a un &
o como un parámetro genérico dentro de <>
.