0Pricing
Lua Academy · Leçon

resume et yield

Échangez des données entre l’appelant et la coroutine avec resume/yield.

resume et yield est une leçon Lua Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Lua Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Lua Academy comprend 4 leçons au total.

Transmettre des valeurs à une coroutine

Les arguments transmis au premier coroutine.resume deviennent les paramètres de la fonction constituant le corps de la coroutine. Les arguments transmis lors des reprises suivantes sont renvoyés par l’appel coroutine.yield() qui a suspendu la coroutine.

local co = coroutine.create(function(a, b)
  print("received:", a, b)        -- 10  20
  local c = coroutine.yield()     -- pauses
  print("after yield:", c)        -- 30
end)

coroutine.resume(co, 10, 20)  -- first call: passes a,b
coroutine.resume(co, 30)      -- subsequent: passed to yield

Valeurs provenant de yield

Les valeurs transmises à coroutine.yield(val1, val2) deviennent les valeurs de retour de l’appel coroutine.resume() qui a suspendu la coroutine au niveau de yield. Ainsi, yield « renvoie » des valeurs à l’appelant.

local co = coroutine.create(function()
  coroutine.yield(1, "hello")
  coroutine.yield(2, "world")
  return 3, "done"
end)

local ok, a, b = coroutine.resume(co)
print(ok, a, b)   -- true  1  hello

ok, a, b = coroutine.resume(co)
print(ok, a, b)   -- true  2  world

ok, a, b = coroutine.resume(co)
print(ok, a, b)   -- true  3  done

Communication bidirectionnelle

Les coroutines permettent une véritable communication bidirectionnelle : l’appelant transmet des données via resume, la coroutine les traite et renvoie des résultats avec yield. Chaque opération resume/yield constitue un échange synchrone.

local co = coroutine.create(function(x)
  while true do
    x = coroutine.yield(x * x)  -- yield x^2, get next x
  end
end)

coroutine.resume(co)  -- start (x=nil initially)
local ok, sq
ok, sq = coroutine.resume(co, 3); print(sq)  -- 9
ok, sq = coroutine.resume(co, 5); print(sq)  -- 25
ok, sq = coroutine.resume(co, 7); print(sq)  -- 49

Producteur-consommateur

Le schéma classique des coroutines : le producteur fournit les éléments un par un avec yield ; le consommateur reprend le producteur chaque fois qu’il a besoin de l’élément suivant. Aucun des deux ne prend d’avance sur l’autre : la synchronisation est parfaite.

local function producer(items)
  return coroutine.create(function()
    for _, item in ipairs(items) do
      coroutine.yield(item)
    end
  end)
end

local pro = producer({"apple","banana","cherry"})

-- Consumer drives the loop
while true do
  local ok, item = coroutine.resume(pro)
  if not ok or item == nil then break end
  print("consumed:", item)
end

Chaîne de traitement avec des coroutines

Reliez plusieurs coroutines pour former une chaîne de traitement. Chaque étape lit les données de l’étape précédente et les transmet à la suivante avec yield. L’étape finale pilote la chaîne en reprenant la dernière étape, ce qui se propage en cascade jusqu’au début de la chaîne.

local function source(items)
  return coroutine.wrap(function()
    for _, v in ipairs(items) do coroutine.yield(v) end
  end)
end

local function filter(iter, pred)
  return coroutine.wrap(function()
    for v in iter do
      if pred(v) then coroutine.yield(v) end
    end
  end)
end

local function map(iter, fn)
  return coroutine.wrap(function()
    for v in iter do coroutine.yield(fn(v)) end
  end)
end

local pipeline = map(filter(source({1,2,3,4,5,6}),
  function(n) return n%2==0 end),
  function(n) return n*n end)

for v in pipeline do io.write(v.." ") end
print()  -- 4 16 36

Coroutines pour simuler l’asynchrone

Sans threads OS, les coroutines peuvent simuler des opérations asynchrones : elles utilisent yield pendant qu’elles « attendent », puis sont reprises lorsque le « résultat » est prêt. Un ordonnanceur reprend alors la coroutine en lui transmettant le résultat.

local scheduler = {}
local current = nil

local function await(key)
  coroutine.yield(key)  -- tell scheduler what we need
  return coroutine.yield()  -- wait for result
end

local co = coroutine.create(function()
  local data = await("fetch:users")
  print("Got users:", data)
end)

-- Start coroutine
local ok, want = coroutine.resume(co)
print("Coroutine wants:", want)  -- fetch:users
-- Simulate delivering the result:
coroutine.resume(co, {{name="Alice"},{name="Bob"}})

yield à l’intérieur d’une fonction

Vous pouvez utiliser yield à l’intérieur de n’importe quelle fonction appelée par une coroutine, et pas seulement dans la fonction de niveau supérieur. yield remonte à travers tous les appels imbriqués jusqu’à l’appel de reprise. On parle alors de « pile d’appels suspendue ».

local function yieldTwice(label)
  coroutine.yield(label .. ":1")
  coroutine.yield(label .. ":2")
end

local co = coroutine.create(function()
  yieldTwice("A")
  yieldTwice("B")
end)

for i = 1, 4 do
  local ok, v = coroutine.resume(co)
  print(v)
end
-- A:1, A:2, B:1, B:2

Les coroutines ne sont pas des threads

Les coroutines Lua ne sont pas des threads OS. Une seule coroutine s’exécute à la fois : il n’y a ni préemption ni parallélisme. Toutes les coroutines partagent un seul thread OS. Pour obtenir un véritable parallélisme, vous avez besoin de plusieurs états Lua dans des threads OS distincts.

-- This is NOT parallel - interleaved execution
local function task(name, n)
  for i = 1, n do
    print(name, i)
    coroutine.yield()
  end
end

local t1 = coroutine.create(function() task("A", 3) end)
local t2 = coroutine.create(function() task("B", 3) end)

-- Must explicitly schedule:
for _ = 1, 3 do
  coroutine.resume(t1)
  coroutine.resume(t2)
end
-- A1, B1, A2, B2, A3, B3 (interleaved, NOT parallel)

État après resume

Vérifiez l’état d’une coroutine pour décider s’il faut la reprendre. Une coroutine qui a terminé son exécution est « morte » : sa reprise renvoie false avec une erreur. Vérifiez toujours l’état avant une reprise dans une boucle.

local co = coroutine.create(function()
  for i = 1, 3 do coroutine.yield(i) end
end)

while coroutine.status(co) ~= "dead" do
  local ok, val = coroutine.resume(co)
  if ok and val ~= nil then
    print("val:", val)
  end
end
-- val: 1, val: 2, val: 3

Plusieurs yield dans un seul resume

Un seul appel à coroutine.resume exécute la coroutine jusqu’au prochain yield ou jusqu’à sa fin. Vous ne pouvez pas faire utiliser yield plusieurs fois à une coroutine lors d’un seul resume : chaque yield la suspend et elle attend le resume suivant.

local co = coroutine.create(function()
  local x = coroutine.yield("first")
  print("got:", x)
  local y = coroutine.yield("second")
  print("got:", y)
end)

local _, v1 = coroutine.resume(co)         -- starts, yields "first"
print("yielded:", v1)                       -- first
local _, v2 = coroutine.resume(co, "a")   -- passes "a", yields "second"
print("yielded:", v2)                       -- second
coroutine.resume(co, "b")                   -- passes "b", coroutine ends

Vérification rapide

Que deviennent les valeurs transmises à coroutine.yield(v1, v2) ?

Récapitulatif : resume et yield

Résumé :

  • Arguments du premier resume → paramètres du corps de la coroutine
  • Arguments des reprises suivantes → renvoyés par le yield() précédent
  • Arguments de yield → renvoyés par le resume() qui a déclenché yield
  • Bidirectionnel : chaque resume/yield est un échange
  • yield fonctionne depuis n’importe quelle fonction imbriquée
  • Les coroutines sont coopératives, pas parallèles

Questions Fréquemment Posées

La leçon « resume et yield » est-elle gratuite ?

Oui — le texte complet de « resume et yield » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Lua Academy, passe à CoddyKit PRO. Le cours Lua Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « resume et yield » ?

Échangez des données entre l’appelant et la coroutine avec resume/yield. Tu pratiques Lua Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Lua Academy ?

Aucune expérience préalable n'est requise. Lua Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « resume et yield » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Lua Academy ?

Oui. Chaque leçon Lua Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Créer des coroutines
  2. resume et yield
  3. État d’une coroutine
  4. Modèle producteur-consommateur
← Retour à Lua Academy