Óxido - Iterador y cierre

En este capítulo, aprenderemos cómo funcionan los iteradores y cierres en RUST.

Iteradores

Un iterador ayuda a iterar sobre una colección de valores como matrices, vectores, mapas, etc. Los iteradores implementan el rasgo Iterator que se define en la biblioteca estándar de Rust. El método iter () devuelve un objeto iterador de la colección. Los valores de un objeto iterador se denominan elementos. El método next () del iterador se puede utilizar para recorrer los elementos. El método next () devuelve un valor None cuando llega al final de la colección.

El siguiente ejemplo usa un iterador para leer valores de una matriz.

fn main() {
   //declare an array
   let a = [10,20,30];

   let mut iter = a.iter(); 
   // fetch an iterator object for the array
   println!("{:?}",iter);

   //fetch individual values from the iterator object
   println!("{:?}",iter.next());
   println!("{:?}",iter.next());
   println!("{:?}",iter.next());
   println!("{:?}",iter.next());
}

Salida

Iter([10, 20, 30])
Some(10)
Some(20)
Some(30)
None

Si una colección como matriz o Vector implementa el rasgo Iterator, entonces se puede recorrer usando la sintaxis for ... como se muestra a continuación-

fn main() {
   let a = [10,20,30];
   let iter = a.iter();
   for data in iter{
      print!("{}\t",data);
   }
}

Salida

10 20 30

Los siguientes 3 métodos devuelven un objeto iterador de una colección, donde T representa los elementos de una colección.

No Señor Métodos y descripción
1

iter()

da un iterador sobre & T (referencia a T)

2

into_iter()

da un iterador sobre T

3

iter_mut()

da un iterador sobre & mut T

Ilustración: iter ()

La función iter () usa el concepto de préstamo. Devuelve una referencia a cada elemento de la colección, dejando la colección intacta y disponible para su reutilización después del ciclo.

fn main() {
   let names = vec!["Kannan", "Mohtashim", "Kiran"];
   for name in names.iter() {
      match name {
         &"Mohtashim" => println!("There is a rustacean among us!"),
         _ => println!("Hello {}", name),
      }
   }
   println!("{:?}",names); 
   // reusing the collection after iteration
}

Salida

Hello Kannan
There is a rustacean among us!
Hello Kiran
["Kannan", "Mohtashim", "Kiran"]

Ilustración - into_iter ()

Esta función utiliza el concepto de propiedad. Mueve los valores de la colección a un objeto iter, es decir, la colección se consume y ya no está disponible para su reutilización.

fn main(){
   let names = vec!["Kannan", "Mohtashim", "Kiran"];
   for name in names.into_iter() {
      match name {
         "Mohtashim" => println!("There is a rustacean among us!"),
         _ => println!("Hello {}", name),
      }
   }
   // cannot reuse the collection after iteration
   //println!("{:?}",names); 
   //Error:Cannot access after ownership move
}

Salida

Hello Kannan
There is a rustacean among us!
Hello Kiran

Ilustración - for e iter_mut ()

Esta función es como la función iter () . Sin embargo, esta función puede modificar elementos dentro de la colección.

fn main() {
   let mut names = vec!["Kannan", "Mohtashim", "Kiran"];
   for name in names.iter_mut() {
      match name {
         &mut "Mohtashim" => println!("There is a rustacean among us!"),
         _ => println!("Hello {}", name),
      }
   }
   println!("{:?}",names);
   //// reusing the collection after iteration
}

Salida

Hello Kannan
There is a rustacean among us!
Hello Kiran
["Kannan", "Mohtashim", "Kiran"]

Cierre

El cierre se refiere a una función dentro de otra función. Estas son funciones anónimas, funciones sin nombre. El cierre se puede utilizar para asignar una función a una variable. Esto permite que un programa pase una función como parámetro a otras funciones. El cierre también se conoce como función en línea. Se puede acceder a las variables de la función externa mediante funciones en línea.

Sintaxis: Definición de un cierre

Una definición de cierre puede tener opcionalmente parámetros. Los parámetros están dentro de dos barras verticales.

let closure_function = |parameter| {
   //logic
}

La sintaxis que invoca un cierre implementa Fnrasgos. Entonces, se puede invocar con() sintaxis.

closure_function(parameter);    //invoking

Ilustración

El siguiente ejemplo define un cierre is_even dentro de la función main () . El cierre devuelve verdadero si un número es par y devuelve falso si el número es impar.

fn main(){
   let is_even = |x| {
      x%2==0
   };
   let no = 13;
   println!("{} is even ? {}",no,is_even(no));
}

Salida

13 is even ? false

Ilustración

fn main(){
   let val = 10; 
   // declared outside
   let closure2 = |x| {
      x + val //inner function accessing outer fn variable
   };
   println!("{}",closure2(2));
}

La función main () declara una variable val y un cierre. El cierre accede a la variable declarada en la función externa main () .

Salida

12