Rouille - Itérateur et fermeture

Dans ce chapitre, nous allons apprendre comment les itérateurs et les fermetures fonctionnent dans RUST.

Itérateurs

Un itérateur permet d'itérer sur une collection de valeurs telles que des tableaux, des vecteurs, des cartes, etc. Les itérateurs implémentent le trait Iterator qui est défini dans la bibliothèque standard de Rust. La méthode iter () retourne un objet itérateur de la collection. Les valeurs d'un objet itérateur sont appelées éléments. La méthode next () de l'itérateur peut être utilisée pour parcourir les éléments. La méthode next () renvoie une valeur None lorsqu'elle atteint la fin de la collection.

L'exemple suivant utilise un itérateur pour lire les valeurs d'un tableau.

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());
}

Production

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

Si une collection telle que array ou Vector implémente le trait Iterator, elle peut être parcourue en utilisant la syntaxe for ... in comme indiqué ci-dessous.

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

Production

10 20 30

Les 3 méthodes suivantes retournent un objet itérateur à partir d'une collection, où T représente les éléments d'une collection.

Sr. Non Méthodes et description
1

iter()

donne un itérateur sur & T (référence à T)

2

into_iter()

donne un itérateur sur T

3

iter_mut()

donne un itérateur sur & mut T

Illustration: iter ()

La fonction iter () utilise le concept d'emprunt. Il renvoie une référence à chaque élément de la collection, laissant la collection intacte et disponible pour une réutilisation après la boucle.

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
}

Production

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

Illustration - into_iter ()

Cette fonction utilise le concept de propriété. Il déplace les valeurs de la collection dans un objet iter, c'est-à-dire que la collection est consommée et qu'elle n'est plus disponible pour une réutilisation.

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
}

Production

Hello Kannan
There is a rustacean among us!
Hello Kiran

Illustration - pour et iter_mut ()

Cette fonction est comme la fonction iter () . Cependant, cette fonction peut modifier les éléments de la collection.

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
}

Production

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

Fermeture

La fermeture fait référence à une fonction dans une autre fonction. Ce sont des fonctions anonymes - des fonctions sans nom. La fermeture peut être utilisée pour affecter une fonction à une variable. Cela permet à un programme de passer une fonction en tant que paramètre à d'autres fonctions. La fermeture est également connue sous le nom de fonction en ligne. Les variables de la fonction externe sont accessibles par des fonctions en ligne.

Syntaxe: Définition d'une fermeture

Une définition de fermeture peut éventuellement avoir des paramètres. Les paramètres sont entourés de deux barres verticales.

let closure_function = |parameter| {
   //logic
}

La syntaxe invoquant une fermeture implémente Fntraits. Ainsi, il peut être invoqué avec() syntaxe.

closure_function(parameter);    //invoking

Illustration

L'exemple suivant définit une fermeture is_even dans la fonction main () . La fermeture renvoie true si un nombre est pair et renvoie false si le nombre est impair.

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

Production

13 is even ? false

Illustration

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

La fonction main () déclare une variable val et une fermeture. La fermeture accède à la variable déclarée dans la fonction externe main () .

Production

12