Aller au contenu principal
ShadowAcademy

Les langages / Lua / Coroutines et iterateurs

Coroutines

Les coroutines sont des fonctions qui peuvent être suspendues et reprises. Elles permettent la programmation coopérative, utile pour les générateurs, la gestion d'état et les tâches asynchrones.

Créer et utiliser une coroutine

-- Créer une coroutine
local co = coroutine.create(function()
  print("Coroutine démarrée")
  coroutine.yield()  -- Pause
  print("Coroutine reprise")
  coroutine.yield()
  print("Coroutine terminée")
end)

-- Vérifier l'état
print(coroutine.status(co))  -- suspended

-- Exécuter
coroutine.resume(co)  -- Coroutine démarrée
print(coroutine.status(co))  -- suspended

coroutine.resume(co)  -- Coroutine reprise
coroutine.resume(co)  -- Coroutine terminée
print(coroutine.status(co))  -- dead

Échanger des valeurs avec yield/resume

-- Coroutine qui produit des valeurs
local producteur = coroutine.create(function()
  for i = 1, 5 do
    print("Production de", i)
    local reponse = coroutine.yield(i)
    print("Reçu:", reponse)
  end
end)

-- Consommer les valeurs
while coroutine.status(producteur) ~= "dead" do
  local ok, valeur = coroutine.resume(producteur, "ACK")
  if valeur then
    print("Consommation de", valeur)
  end
end

Générateur avec coroutine

-- Générateur de Fibonacci
function fibonacci()
  return coroutine.wrap(function()
    local a, b = 0, 1
    while true do
      coroutine.yield(a)
      a, b = b, a + b
    end
  end)
end

-- Utiliser le générateur
local fib = fibonacci()
for i = 1, 10 do
  print(fib())  -- 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
end

-- Générateur de nombres premiers
function premiers(max)
  return coroutine.wrap(function()
    for n = 2, max do
      local estPremier = true
      for i = 2, math.sqrt(n) do
        if n % i == 0 then
          estPremier = false
          break
        end
      end
      if estPremier then
        coroutine.yield(n)
      end
    end
  end)
end

for p in premiers(20) do
  print(p)  -- 2, 3, 5, 7, 11, 13, 17, 19
end

Pipeline de traitement

-- Pipeline avec coroutines
function source(data)
  return coroutine.wrap(function()
    for _, v in ipairs(data) do
      coroutine.yield(v)
    end
  end)
end

function filtrer(input, fn)
  return coroutine.wrap(function()
    for v in input do
      if fn(v) then
        coroutine.yield(v)
      end
    end
  end)
end

function transformer(input, fn)
  return coroutine.wrap(function()
    for v in input do
      coroutine.yield(fn(v))
    end
  end)
end

-- Utiliser le pipeline
local donnees = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
local resultat = transformer(
  filtrer(
    source(donnees),
    function(x) return x % 2 == 0 end
  ),
  function(x) return x * x end
)

for v in resultat do
  print(v)  -- 4, 16, 36, 64, 100
end

1 exercice pour cette lecon

Les exercices demandent un compte : il faut bien enregistrer votre progression quelque part. La lecture, elle, reste libre. Creer un compte

  • Coroutine basique difficile 35 XP