0Pricing
Lua Academy · Lezione

resume e yield

Scambi dati tra chiamante e coroutine con resume/yield.

resume e yield è una lezione Lua Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Lua Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Lua Academy include 4 lezioni in totale.

Passaggio di valori alla coroutine

Gli argomenti passati alla prima chiamata di coroutine.resume diventano i parametri della funzione che costituisce il corpo della coroutine. Gli argomenti passati alle chiamate successive vengono restituiti dalla chiamata a coroutine.yield() che ha sospeso 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

Valori restituiti da yield

I valori passati a coroutine.yield(val1, val2) diventano i valori restituiti dalla chiamata a coroutine.resume() che si è fermata su yield. In questo modo, yield «restituisce» valori al chiamante.

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

Comunicazione bidirezionale

Le coroutine consentono una vera comunicazione bidirezionale: il chiamante passa i dati tramite resume, la coroutine li elabora e restituisce i risultati tramite yield. Ogni chiamata a resume/yield è uno scambio sincrono.

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

Produttore-consumatore

Il modello classico delle coroutine: il produttore restituisce gli elementi uno alla volta tramite yield; il consumatore riprende il produttore ogni volta che ha bisogno dell'elemento successivo. Nessuno dei due procede in anticipo rispetto all'altro: la sincronizzazione è perfetta.

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

Pipeline con le coroutine

Colleghi più coroutine in una pipeline. Ogni fase legge dalla fase precedente e restituisce valori tramite yield alla fase successiva. La fase finale esegue la pipeline riprendendo l'ultima fase, che propaga la richiesta a ritroso lungo la catena.

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

Coroutine per simulare operazioni asincrone

Senza thread del sistema operativo, le coroutine possono simulare operazioni asincrone: esegua yield mentre «attendono» e riprenda la coroutine quando il «risultato» è pronto. Uno scheduler riprende la coroutine passando il risultato.

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 all'interno di una funzione

È possibile eseguire yield dall'interno di qualsiasi funzione chiamata da una coroutine, non solo dalla funzione di livello superiore. L'operazione yield risale attraverso tutte le chiamate annidate fino alla chiamata a resume. Questo è detto «stack di chiamate sospeso».

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

Le coroutine non sono thread

Le coroutine di Lua non sono thread del sistema operativo. Viene eseguita una sola coroutine alla volta: non esistono prelazione né parallelismo. Tutte le coroutine condividono un singolo thread del sistema operativo. Per ottenere un vero parallelismo sono necessari più stati Lua in thread del sistema operativo separati.

-- 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)

Stato dopo resume

Controlli lo stato della coroutine per decidere se riprenderla. Una coroutine che ha terminato l'esecuzione, cioè è uscita dal proprio corpo, è «terminata»: riprenderla restituisce false insieme a un errore. Controlli sempre lo stato prima di riprendere una coroutine nei cicli.

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

Più yield in una sola chiamata a resume

Una singola chiamata a coroutine.resume esegue la coroutine fino al yield successivo o fino alla sua conclusione. Non è possibile far eseguire più yield a una coroutine durante una sola chiamata a resume: ogni yield sospende la coroutine, che attende la chiamata a resume successiva.

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

Verifica rapida

In cosa si trasformano i valori passati a coroutine.yield(v1, v2)?

Riepilogo: resume e yield

Riepilogo:

  • Argomenti della prima chiamata a resume → parametri del corpo della coroutine
  • Argomenti delle chiamate successive a resume → restituiti dal yield() precedente
  • Argomenti di yield → restituiti dalla chiamata a resume() che ha attivato yield
  • Bidirezionalità: ogni resume/yield è uno scambio
  • È possibile eseguire yield da qualsiasi funzione annidata
  • Le coroutine sono cooperative, non parallele

Domande Frequenti

La lezione «resume e yield» è gratuita?

Sì — il testo completo di «resume e yield» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Lua Academy, passa a CoddyKit PRO. Il corso Lua Academy include 4 lezioni in totale.

Cosa imparerò in «resume e yield»?

Scambi dati tra chiamante e coroutine con resume/yield. Eserciti Lua Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Lua Academy?

Non è richiesta alcuna esperienza precedente. Lua Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «resume e yield»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Lua Academy?

Sì. Ogni lezione Lua Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Creazione delle coroutine
  2. resume e yield
  3. Stato delle coroutine
  4. Pattern produttore-consumatore
← Torna a Lua Academy