Lua - Coroutines: A Beginner's Guide

Introduction

Bonjour là-bas, futurs programmeurs ! Aujourd'hui, nous allons entreprendre un voyage passionnant à travers le monde des coroutines Lua. Je sais ce que vous pourriez être en train de penser : "Coroutines ? Ça paraît compliqué !" Mais ne vous inquiétez pas, je suis là pour vous guider à travers ce concept étape par étape, tout comme j'ai fait pour des centaines d'étudiants au fil des ans.

Lua - Coroutines

Imaginez que vous lisez un livre passionnant, mais que vous avez besoin de faire une pause. Vous placez un signet, fermez le livre, et revenez plus tard pour reprendre exactement là où vous étiez. C'est essentiellement ce que font les coroutines dans la programmation ! Elles permettent à un programme de suspendre son exécution à un certain point et de reprendre plus tard exactement à cet endroit.

En Lua, les coroutines sont un moyen d'avoir plusieurs "threads" d'exécution au sein d'un seul programme. Mais contrairement aux threads traditionnels, les coroutines sont coopératives, ce qui signifie qu'elles cèdent volontairement le contrôle plutôt que d'être préemtives par le système d'exploitation.

Fonctions Disponibles dans les Coroutines

Avant de plonger dans des exemples, examinons les principales fonctions que nous utilisons avec les coroutines en Lua. Je les présente dans un tableau pour une référence facile :

Fonction Description
coroutine.create() Crée une nouvelle coroutine
coroutine.resume() Démarre ou continue l'exécution d'une coroutine
coroutine.yield() Suspend l'exécution d'une coroutine
coroutine.status() Retourne l'état d'une coroutine
coroutine.wrap() Crée une fonction qui reprend une coroutine

Ne vous inquiétez pas si cela ne vous semble pas tout à fait clair pour le moment. Nous explorerons chacun de ces points dans nos exemples !

Exemple

Commençons par un exemple simple pour voir les coroutines en action :

function count(start, finish)
for i = start, finish do
print(i)
coroutine.yield()
end
end

co = coroutine.create(count)

coroutine.resume(co, 1, 5)
print("Retour dans le programme principal")
coroutine.resume(co)
print("Encore une fois dans le programme principal")
coroutine.resume(co)
print("Une dernière fois dans le programme principal")
coroutine.resume(co)

Que Fait l'Exemple ci-dessus ?

Décomposons cela pas à pas :

  1. Nous définissons une fonction appelée count qui prend deux paramètres : start et finish.

  2. À l'intérieur de la fonction, nous avons une boucle for qui imprime des nombres de start à finish. Après chaque impression, elle appelle coroutine.yield(), ce qui suspend l'exécution de la fonction.

  3. Nous créons une coroutine en utilisant coroutine.create(count). Cela ne démarre pas encore la fonction ; cela ne fait que la préparer pour qu'elle puisse s'exécuter en tant que coroutine.

  4. Nous utilisons coroutine.resume(co, 1, 5) pour démarrer la coroutine. Les valeurs 1 et 5 sont passées comme arguments à la fonction count.

  5. La coroutine imprime 1 puis se suspend. Le contrôle retourne au programme principal, qui imprime "Retour dans le programme principal".

  6. Nous reprenons la coroutine à nouveau avec coroutine.resume(co). Elle reprend là où elle s'était arrêtée, imprime 2, puis se suspend à nouveau.

  7. Ce processus continue jusqu'à ce que la coroutine termine son exécution.

Lorsque vous exécutez ce programme, vous verrez les nombres entrelacés avec les messages "Retour dans le programme principal". C'est comme si le programme principal et la coroutine se relaient !

Un Autre Exemple de Coroutine

Regardons un autre exemple pour renforcer notre compréhension :

function producer()
return coroutine.create(function()
for i = 1, 5 do
coroutine.yield("Item " .. i)
end
end)
end

function consumer(prod)
local status, value = coroutine.resume(prod)
while status and value do
print("Consommé : " .. value)
status, value = coroutine.resume(prod)
end
end

-- Créer la coroutine productrice
local prod = producer()

-- Commencer la consommation
consumer(prod)

Dans cet exemple, nous avons une situation producteur-consommateur :

  1. La fonction producer crée une coroutine qui génère des éléments un par un.

  2. La fonction consumer prend une coroutine productrice et consomme tous ses éléments.

  3. Nous créons une coroutine productrice et la passons au consommateur.

Lorsque vous exécutez cela, vous verrez :

Consommé : Item 1
Consommé : Item 2
Consommé : Item 3
Consommé : Item 4
Consommé : Item 5

Cela montre comment les coroutines peuvent être utilisées pour implémenter un multitâche coopératif. Le producteur génère des éléments à son propre rythme, et le consommateur les traite à mesure qu'ils deviennent disponibles.

Les coroutines sont particulièrement utiles dans des scénarios comme le développement de jeux (pour gérer les états du jeu), l'implémentation d'itérateurs, ou la gestion des opérations asynchrones de manière synchrone.

Souvenez-vous, la pratique rend parfait ! Essayez de modifier ces exemples, jouez avec le code, et voyez ce qui se passe. C'est la meilleure façon d'apprendre à programmer. Et qui sait ? Peut-être que vous enseignerez un jour les coroutines à une nouvelle génération de programmeurs !

Bonne programmation, futurs maîtres Lua !

Credits: Image by storyset