Lua Academy · Pelajaran

resume dan yield

Tukar data antara pemanggil dengan coroutine menggunakan resume/yield.

Pelajaran 2 daripada 412 langkah

resume dan yield ialah pelajaran Lua Academy percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Lua Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Lua Academy merangkumi sejumlah 4 pelajaran.

Menghantar Nilai kepada Coroutine

Argumen yang dihantar kepada coroutine.resume pertama menjadi parameter fungsi bagi badan coroutine. Argumen yang dihantar kepada penyambungan semula seterusnya dikembalikan oleh panggilan coroutine.yield() yang menjeda 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

Nilai daripada yield

Nilai yang dihantar kepada coroutine.yield(val1, val2) menjadi nilai pulangan bagi panggilan coroutine.resume() yang dijeda pada yield tersebut. Jadi, yield "memulangkan" nilai kepada pemanggil.

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

Komunikasi Dua Hala

Coroutine membolehkan komunikasi dua hala yang sebenar: pemanggil menghantar data melalui resume, coroutine memprosesnya lalu menghantar hasil kembali melalui yield. Setiap resume/yield ialah pertukaran segerak.

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

Pengeluar-Pengguna

Pola coroutine klasik: pengeluar menghasilkan item satu demi satu; pengguna menyambung semula pengeluar setiap kali memerlukan item seterusnya. Tiada satu pun berjalan mendahului yang lain — penyegerakan yang sempurna.

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

Saluran Paip dengan Coroutine

Rantaikan beberapa coroutine sebagai saluran paip. Setiap peringkat membaca daripada peringkat sebelumnya dan menghasilkan nilai melalui yield kepada peringkat seterusnya. Peringkat terakhir menggerakkan saluran paip dengan menyambung semula peringkat terakhir, lalu mencetuskan aliran kembali melalui rantaian tersebut.

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 untuk Simulasi Tak Segerak

Tanpa thread OS, coroutine boleh mensimulasikan operasi tak segerak: lakukan yield semasa "menunggu" dan sambung semula apabila "hasil" sudah tersedia. Penjadual menyambung semula coroutine dengan hasil tersebut.

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 di Dalam Fungsi

Anda boleh melakukan yield dari dalam mana-mana fungsi yang dipanggil oleh coroutine, bukan hanya fungsi peringkat teratas. Yield bergerak naik melalui semua panggilan bersarang sehingga kembali kepada resume. Ini dipanggil "stack panggilan tergantung".

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

Coroutine Bukan Thread

Coroutine Lua bukan thread OS. Hanya satu coroutine berjalan pada satu-satu masa; tiada prapengambilalihan atau pelaksanaan selari. Semua coroutine berkongsi satu thread OS. Untuk pelaksanaan selari sebenar, anda memerlukan beberapa keadaan Lua dalam thread OS yang berasingan.

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

Status Selepas Penyambungan Semula

Semak status coroutine untuk menentukan sama ada perlu menyambung semula. Coroutine yang telah selesai (kembali daripada badannya) berada dalam keadaan "mati" — penyambungan semula akan mengembalikan false bersama ralat. Sentiasa semak status sebelum menyambung semula dalam gelung.

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

Beberapa yield dalam Satu Penyambungan Semula

Satu panggilan kepada coroutine.resume menjalankan coroutine sehingga yield seterusnya atau sehingga coroutine tamat. Anda tidak boleh membuat coroutine melakukan yield beberapa kali dalam satu penyambungan semula — setiap yield menggantungnya dan menunggu penyambungan semula seterusnya.

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

Semakan Pantas

Nilai yang dihantar kepada coroutine.yield(v1, v2) menjadi apa?

Imbas Kembali: resume dan yield

Ringkasan:

  • Argumen resume pertama → parameter badan coroutine
  • Argumen resume seterusnya → dikembalikan oleh yield() sebelumnya
  • Argumen yield → dikembalikan oleh resume() yang mencetuskan yield tersebut
  • Dua hala: setiap resume/yield ialah satu pertukaran
  • yield daripada mana-mana fungsi bersarang boleh digunakan
  • Coroutine: koperatif, bukan selari
Percuma untuk bermula

Pelajari Lua dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
40
Pelajaran
159

Soalan Lazim

Adakah pelajaran “resume dan yield” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Lua Academy, termasuk “resume dan yield”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Lua Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “resume dan yield”?

Tukar data antara pemanggil dengan coroutine menggunakan resume/yield. Anda berlatih Lua Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Lua Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Lua Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.

Berapa lamakah pelajaran “resume dan yield” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Lua Academy ini?

Ya. Setiap pelajaran Lua Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Mencipta Coroutine
  2. resume dan yield
  3. Status Coroutine
  4. Corak Pengeluar-Pengguna
← Kembali ke Lua Academy