Iteradores
El trato Iterator se utiliza para implementar iteradores sobre colecciones como arrays.
El trato solo requiere que se defina un método para el elemento next, el cual puede definirse manualmente en un bloque impl o definirse automáticamente (como en arrays y rangos).
Como una conveniencia para situaciones comunes, la construcción for convierte algunas colecciones en iteradores utilizando el método .into_iter().
struct Fibonacci {
curr: u32,
next: u32,
}
// Implemente `Iterator` para `Fibonacci`.
// El trato `Iterator` solo requiere que se defina un método para el elemento `next`.
impl Iterator for Fibonacci {
// Podemos referirnos a este tipo utilizando Self::Item
type Item = u32;
// Aquí, definimos la secuencia utilizando `.curr` y `.next`.
// El tipo de retorno es `Option<T>`:
// * Cuando el `Iterator` termina, se devuelve `None`.
// * De lo contrario, el siguiente valor se envuelve en `Some` y se devuelve.
// Utilizamos Self::Item en el tipo de retorno, para que podamos cambiar
// el tipo sin tener que actualizar las firmas de función.
fn next(&mut self) -> Option<Self::Item> {
let current = self.curr;
self.curr = self.next;
self.next = current + self.next;
// Dado que no hay un punto final en una secuencia de Fibonacci, el `Iterator`
// nunca devolverá `None`, y siempre se devuelve `Some`.
Some(current)
}
}
// Devuelve un generador de secuencia de Fibonacci
fn fibonacci() -> Fibonacci {
Fibonacci { curr: 0, next: 1 }
}
fn main() {
// `0..3` es un `Iterator` que genera: 0, 1 y 2.
let mut sequence = 0..3;
println!("Cuatro llamadas consecutivas a `next` en 0..3");
println!("> {:?}", sequence.next());
println!("> {:?}", sequence.next());
println!("> {:?}", sequence.next());
println!("> {:?}", sequence.next());
// `for` recorre un `Iterator` hasta que devuelve `None`.
// Cada valor `Some` se desenvuelve y se asigna a una variable (aquí, `i`).
println!("Iterar a través de 0..3 utilizando `for`");
for i in 0..3 {
println!("> {}", i);
}
// El método `take(n)` reduce un `Iterator` a sus primeros `n` términos.
println!("Los primeros cuatro términos de la secuencia de Fibonacci son: ");
for i in fibonacci().take(4) {
println!("> {}", i);
}
// El método `skip(n)` acorta un `Iterator` eliminando sus primeros `n` términos.
println!("Los siguientes cuatro términos de la secuencia de Fibonacci son: ");
for i in fibonacci().skip(4).take(4) {
println!("> {}", i);
}
let array = [1u32, 3, 3, 7];
// El método `iter` produce un `Iterator` sobre un array/slice.
println!("Iterar el siguiente array {:?}", &array);
for i in array.iter() {
println!("> {}", i);
}
}