Lua - Itérateurs

Iterator est une construction qui vous permet de parcourir les éléments de la soi-disant collection ou conteneur. Dans Lua, ces collections font souvent référence à des tables, qui sont utilisées pour créer diverses structures de données comme un tableau.

Générique pour Iterator

Un générique pour itérateur fournit des paires de valeurs clés de chaque élément de la collection. Un exemple simple est donné ci-dessous.

array = {"Lua", "Tutorial"}

for key,value in ipairs(array) 
do
   print(key, value)
end

Lorsque nous exécutons le code ci-dessus, nous obtiendrons la sortie suivante -

1  Lua
2  Tutorial

L'exemple ci-dessus utilise la fonction d'itérateur ipairs par défaut fournie par Lua.

Dans Lua, nous utilisons des fonctions pour représenter les itérateurs. Sur la base de la maintenance de l'état dans ces fonctions d'itération, nous avons deux types principaux -

  • Itérateurs apatrides
  • Itérateurs avec état

Itérateurs apatrides

Par le nom lui-même, nous pouvons comprendre que ce type de fonction d'itérateur ne conserve aucun état.

Voyons maintenant un exemple de création de notre propre itérateur en utilisant une fonction simple qui imprime les carrés de n Nombres.

function square(iteratorMaxCount,currentNumber)

   if currentNumber<iteratorMaxCount
   then
      currentNumber = currentNumber+1
      return currentNumber, currentNumber*currentNumber
   end
	
end

for i,n in square,3,0
do
   print(i,n)
end

Lorsque nous exécutons le programme ci-dessus, nous obtiendrons la sortie suivante.

1	1
2	4
3	9

Le code ci-dessus peut être légèrement modifié pour imiter le fonctionnement de la fonction ipairs des itérateurs. Il est montré ci-dessous.

function square(iteratorMaxCount,currentNumber)

   if currentNumber<iteratorMaxCount
   then
      currentNumber = currentNumber+1
      return currentNumber, currentNumber*currentNumber
   end
	
end

function squares(iteratorMaxCount)
   return square,iteratorMaxCount,0
end  

for i,n in squares(3)
do 
   print(i,n)
end

Lorsque nous exécutons le programme ci-dessus, nous obtiendrons la sortie suivante.

1	1
2	4
3	9

Itérateurs avec état

L'exemple précédent d'itération utilisant la fonction ne conserve pas l'état. Chaque fois que la fonction est appelée, elle renvoie l'élément suivant de la collection en fonction d'une deuxième variable envoyée à la fonction. Pour conserver l'état de l'élément actuel, des fermetures sont utilisées. La fermeture conserve les valeurs des variables entre les appels de fonctions. Pour créer une nouvelle fermeture, nous créons deux fonctions dont la fermeture elle-même et une usine, la fonction qui crée la fermeture.

Voyons maintenant un exemple de création de notre propre itérateur dans lequel nous utiliserons des fermetures.

array = {"Lua", "Tutorial"}

function elementIterator (collection)

   local index = 0
   local count = #collection
	
   -- The closure function is returned
	
   return function ()
      index = index + 1
		
      if index <= count
      then
         -- return the current element of the iterator
         return collection[index]
      end
		
   end
	
end

for element in elementIterator(array)
do
   print(element)
end

Lorsque nous exécutons le programme ci-dessus, nous obtiendrons la sortie suivante.

Lua
Tutorial

Dans l'exemple ci-dessus, nous pouvons voir que elementIterator a une autre méthode à l'intérieur qui utilise l'index et le nombre de variables externes locales pour renvoyer chacun des éléments de la collection en incrémentant l'index chaque fois que la fonction est appelée.

Nous pouvons créer nos propres itérateurs de fonction en utilisant la fermeture comme indiqué ci-dessus et il peut retourner plusieurs éléments pour chaque fois que nous itérons dans la collection.