... jusqu'au premier élément nil.
Un itérateur est un objet qui peut être utilisé pour parcourir certains ou tous les éléments d'un conteneur de bibliothèque de modèles standard. Chaque objet itérateur représente une adresse définie dans le conteneur.
En Lua, un itérateur est une structure qui prend en charge les types de pointeurs. Il peut parcourir chaque élément d'une collection.
Itérateur for générique
Le for générique stocke la fonction itératrice en interne. En fait, il stocke trois valeurs : la fonction itératrice, la constante d'état et la variable de contrôle.
L'itérateur for générique fournit les paires clé/valeur de la collection. La syntaxe est la suivante :
for k, v in pairs(t) do
print(k, v)
end
Dans le code ci-dessus, k, v constituent la liste de variables ; pairs(t) est la liste d'expressions.
Regardez l'exemple suivant :
Exemple
for key,value in ipairs(array)
do
print(key, value)
end
La sortie de l'exécution du code ci-dessus est :
1 Google 2 Example
Dans l'exemple ci-dessus, nous avons utilisé la fonction itératrice ipairs fournie par défaut par Lua.
Voyons maintenant le processus d'exécution du for générique :
- Premièrement, initialiser : évaluer l'expression après `in`. L'expression doit renvoyer les trois valeurs nécessaires au for générique : la fonction itératrice, la constante d'état et la variable de contrôle. Comme pour l'affectation multiple, si l'expression renvoie moins de trois valeurs, celles qui manquent sont automatiquement remplies avec nil, et les valeurs supplémentaires sont ignorées.
- Deuxièmement, appeler la fonction itératrice avec la constante d'état et la variable de contrôle comme arguments (note : pour la structure for, la constante d'état est inutile ; elle est seulement obtenue lors de l'initialisation et transmise à la fonction itératrice).
- Troisièmement, affecter les valeurs renvoyées par la fonction itératrice à la liste de variables.
- Quatrièmement, si la première valeur renvoyée est nil, la boucle se termine ; sinon, exécutez le corps de la boucle.
- Cinquièmement, revenez à la deuxième étape et appelez à nouveau la fonction d'itération.
En Lua, nous utilisons souvent des fonctions pour décrire des itérateurs. Chaque fois que la fonction est appelée, elle renvoie l'élément suivant de la collection. Les itérateurs Lua comprennent les deux types suivants :
- Itérateurs sans état
- Itérateurs à états multiples
Itérateurs sans état
Un itérateur sans état est un itérateur qui ne conserve aucun état. Par conséquent, dans les boucles, nous pouvons utiliser des itérateurs sans état pour éviter le coût supplémentaire de création de fermetures.
À chaque itération, la fonction d'itération est appelée avec les valeurs de deux variables (la constante d'état et la variable de contrôle) comme arguments. Un itérateur sans état peut obtenir l'élément suivant en utilisant uniquement ces deux valeurs.
Un exemple typique et simple d'un tel itérateur sans état est ipairs, qui parcourt chaque élément d'un tableau dont les indices doivent être numériques.
L'exemple suivant utilise une simple fonction pour implémenter un itérateur qui calcule le carré d'un nombre n :
Exemple
if currentNumber<iteratorMaxCount
puis
currentNumber = currentNumber+1
return currentNumber, currentNumber*currentNumber
end
end
for i,n in square,3,0
do
print(i,n)
end
La sortie de l'exemple ci-dessus est :
1 1 2 4 3 9
L'état d'itération comprend la table parcourue (la constante d'état, qui ne change pas pendant la boucle) et l'index courant (la variable de contrôle). ipairs et la fonction d'itérateur sont tous deux très simples. En Lua, nous pouvons l'implémenter comme ceci :
Exemple
i = i + 1
local v = a[i]
if v then
return i, v
end
end
function ipairs (a)
return iter, a, 0
end
Lorsque Lua appelle ipairs(a) pour démarrer la boucle, il obtient trois valeurs : la fonction d'itérateur iter, la constante d'état a et la valeur initiale de la variable de contrôle 0. Ensuite, Lua appelle iter(a,0) et renvoie 1, a
Itérateurs à états multiples
Dans de nombreux cas, les itérateurs doivent stocker plusieurs informations d'état plutôt que simplement une constante d'état et une variable de contrôle. La méthode la plus simple consiste à utiliser des fermetures. Une autre méthode consiste à encapsuler toutes les informations d'état dans une table et à utiliser la table comme constante d'état de l'itérateur. Dans ce cas, comme toutes les informations peuvent être stockées dans la table, la fonction d'itérateur n'a généralement pas besoin d'un second paramètre.
Dans l'exemple suivant, nous avons créé notre propre itérateur :
Exemple
function elementIterator (collection)
local index = 0
local count = #collection
-- fonction de fermeture
return function ()
index = index + 1
if index <= count
puis
-- renvoyer l'élément courant de l'itérateur
return collection[index]
end
end
end
for element in elementIterator(array)
do
print(element)
end
La sortie de l'exemple ci-dessus est :
Google Example
Dans l'exemple ci-dessus, nous pouvons voir que elementIterator utilise une fonction de fermeture pour calculer la taille de la collection et afficher chaque élément.
Autres extensions