0Pricing
Lua Academy · Lekcja

resume i yield

Proszę wymieniać dane między wywołującym a korutyną za pomocą resume/yield.

resume i yield to bezpłatna lekcja Lua Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Lua Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Lua Academy zawiera 4 lekcji w sumie.

Przekazywanie wartości do korutyny

Argumenty przekazane do pierwszego wywołania coroutine.resume stają się parametrami funkcji będącej ciałem korutyny. Argumenty przekazane do kolejnych wznowień są zwracane przez wywołanie coroutine.yield(), które wstrzymało korutynę.

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

Wartości z yield

Wartości przekazane do coroutine.yield(val1, val2) stają się wartościami zwracanymi przez wywołanie coroutine.resume(), które wstrzymało się na yield. Oznacza to, że yield „zwraca” wartości do kodu wywołującego.

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

Komunikacja dwukierunkowa

Korutyny umożliwiają prawdziwą komunikację dwukierunkową: kod wywołujący przekazuje dane za pomocą resume, korutyna je przetwarza i przekazuje wyniki z powrotem za pomocą yield. Każda para resume/yield jest synchroniczną wymianą danych.

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

Producent–konsument

Klasyczny wzorzec użycia korutyn: producent zwraca elementy pojedynczo za pomocą yield, a konsument wznawia producenta, gdy potrzebuje kolejnego elementu. Żaden z nich nie wyprzedza drugiego — zapewnia to idealną synchronizację.

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

Potok z korutynami

Połącz wiele korutyn w potok. Każdy etap odczytuje dane z poprzedniego etapu i przekazuje je do następnego za pomocą yield. Ostatni etap napędza potok, wznawiając ostatnią korutynę, co uruchamia kaskadę wywołań z powrotem przez cały łańcuch.

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

Korutyny do symulowania operacji asynchronicznych

Bez wątków systemu operacyjnego korutyny mogą symulować operacje asynchroniczne: wykonują yield podczas „oczekiwania”, a następnie są wznawiane, gdy „wynik” jest gotowy. Harmonogram wznawia korutynę, przekazując jej wynik.

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 wewnątrz funkcji

Można wykonać yield wewnątrz dowolnej funkcji wywołanej przez korutynę, a nie tylko wewnątrz funkcji najwyższego poziomu. Yield przechodzi przez wszystkie zagnieżdżone wywołania aż do resume. Nazywa się to „wstrzymanym stosem wywołań”.

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

Korutyny to nie wątki

Korutyny Lua nie są wątkami systemu operacyjnego. W danym momencie działa tylko jedna korutyna — nie ma wywłaszczania ani równoległości. Wszystkie korutyny współdzielą jeden wątek systemu operacyjnego. Do uzyskania prawdziwego przetwarzania równoległego potrzebnych jest wiele stanów Lua działających w osobnych wątkach systemu operacyjnego.

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

Stan po wznowieniu

Należy sprawdzać stan korutyny, aby zdecydować, czy można wznowić ją ponownie. Korutyna, która zakończyła działanie, czyli zwróciła wynik ze swojego ciała, jest „zakończona” — wznowienie jej zwraca false i komunikat błędu. W pętlach należy zawsze sprawdzać stan przed wznowieniem.

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

Wiele wywołań yield w jednym resume

Pojedyncze wywołanie coroutine.resume uruchamia korutynę aż do napotkania następnego yield albo do jej zakończenia. Nie można sprawić, by korutyna wykonała yield wiele razy podczas jednego resume — każde yield wstrzymuje korutynę i oczekuje na kolejne resume.

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

Szybkie sprawdzenie

W co stają się wartości przekazane do coroutine.yield(v1, v2)?

Podsumowanie: resume i yield

Podsumowanie:

  • Argumenty pierwszego resume → parametry ciała korutyny
  • Argumenty kolejnych resume → wartości zwracane przez poprzednie yield()
  • Argumenty yield → wartości zwracane przez resume(), które wywołało dane yield
  • Dwukierunkowość: każda para resume/yield jest wymianą danych
  • yield działa także z dowolnej zagnieżdżonej funkcji
  • Korutyny działają kooperatywnie, a nie równolegle

Często zadawane pytania

Czy lekcja „resume i yield” jest bezpłatna?

Tak — pełny tekst „resume i yield” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Lua Academy, przejdź na CoddyKit PRO. Kurs Lua Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „resume i yield”?

Proszę wymieniać dane między wywołującym a korutyną za pomocą resume/yield. Ćwiczysz Lua Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Lua Academy?

Nie wymagamy żadnego doświadczenia. Lua Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „resume i yield”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Lua Academy?

Tak. Każda lekcja Lua Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Tworzenie korutyn
  2. resume i yield
  3. Stan korutyny
  4. Wzorzec producent-konsument
← Powrót do Lua Academy