إنشاء البرامج التعاونية
أنشئ برامج تعاونية باستخدام coroutine.create وcoroutine.wrap
إنشاء البرامج التعاونية درس مجاني في Lua Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Lua Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Lua Academy 4 دروس في المجموع.
ما هي Coroutine؟
Coroutine هي دالة يمكنها إيقاف تنفيذها مؤقتًا (yield) ثم استئنافه لاحقًا من الموضع الذي توقفت عنده. وعلى خلاف الخيوط، تعمل Coroutines بأسلوب تعاوني؛ إذ تعمل واحدة فقط في كل مرة، وتتنازل صراحةً عن التحكم. وتمتلك Coroutines في Lua مكدسًا ومتغيرات محلية خاصة بها.
local co = coroutine.create(function()
print("start")
coroutine.yield()
print("resumed")
coroutine.yield()
print("done")
end)
print(coroutine.status(co)) -- suspended
coroutine.resume(co) -- start
print(coroutine.status(co)) -- suspended
coroutine.resume(co) -- resumedcoroutine.create مقابل coroutine.wrap
تنشئ coroutine.create(fn) Coroutine وتعيد كائن Coroutine من النوع thread. أما coroutine.wrap(fn) فتنشئ Coroutine وتعيد دالة يؤدي استدعاؤها إلى استئنافها. تكون wrap أبسط، لكنها تخفي كائن Coroutine.
-- create: returns coroutine object
local co = coroutine.create(function(x)
return x * 2
end)
local ok, val = coroutine.resume(co, 5)
print(ok, val) -- true 10
-- wrap: returns a resumable function
local gen = coroutine.wrap(function(x)
return x * 3
end)
print(gen(5)) -- 15دورة حياة Coroutine
لدى Coroutine أربع حالات: معلّقة (لا تعمل)، وقيد التشغيل (تُنفَّذ حاليًا)، ومنتهية (أعادت قيمة أو حدث فيها خطأ)، وعادية (متوقفة مؤقتًا لأنها استأنفت Coroutine أخرى). تحقّقوا من الحالة باستخدام coroutine.status(co).
local co = coroutine.create(function()
coroutine.yield()
end)
print(coroutine.status(co)) -- suspended
coroutine.resume(co) -- runs until yield
print(coroutine.status(co)) -- suspended again
coroutine.resume(co) -- runs until end
print(coroutine.status(co)) -- deadتشغيل عدة Coroutines
أنشئوا عدة Coroutines وشغّلوها بالتناوب من خلال استئناف كل منها بدوره. يحاكي ذلك التنفيذ المتزامن (تعدد المهام التعاوني). وتحافظ كل Coroutine على حالتها بين عمليات yield.
local function worker(name, steps)
for i = 1, steps do
print(name .. ": step " .. i)
coroutine.yield()
end
end
local co1 = coroutine.create(function() worker("A", 3) end)
local co2 = coroutine.create(function() worker("B", 3) end)
for _ = 1, 3 do
coroutine.resume(co1)
coroutine.resume(co2)
end
-- A:1, B:1, A:2, B:2, A:3, B:3التكرار باستخدام coroutine.wrap
يُستخدم coroutine.wrap عادةً لإنشاء مكررات. وتُستدعى الدالة المُعادة في كل مرة يتقدم فيها المكرر. وعندما ينتهي جسم Coroutine، ترفع الدالة خطأً؛ لذا استخدموا pcall أو تحقّقوا من الحالة عند الحاجة.
local function range(n)
return coroutine.wrap(function()
for i = 1, n do
coroutine.yield(i)
end
end)
end
for v in range(5) do
io.write(v .. " ")
end
print() -- 1 2 3 4 5الأخطاء في Coroutines
إذا رفعت Coroutine خطأً، يعيد coroutine.resume القيمة false متبوعة برسالة الخطأ. وتنتقل Coroutine إلى الحالة dead. ولا يمكن استئناف Coroutine منتهية مرة أخرى.
local co = coroutine.create(function(x)
if x < 0 then error("negative input: " .. x) end
return math.sqrt(x)
end)
local ok, val = coroutine.resume(co, -1)
print(ok, val) -- false input:2: negative input: -1
print(coroutine.status(co)) -- dead
-- Can't resume a dead coroutine:
ok, val = coroutine.resume(co)
print(ok, val) -- false cannot resume dead coroutineهوية Coroutine
يعيد coroutine.running() الـCoroutine قيد التشغيل حاليًا، وقيمة منطقية تشير إلى ما إذا كانت هي الخيط الرئيسي. استخدموا ذلك داخل Coroutine للحصول على مرجع إليها.
local co = coroutine.create(function()
local self, isMain = coroutine.running()
print("type:", type(self)) -- thread
print("isMain:", isMain) -- false
print("status:", coroutine.status(self)) -- running
end)
coroutine.resume(co)
-- In main thread:
local main, isMain = coroutine.running()
print("main isMain:", isMain) -- trueمولّد لا نهائي
يمكن أن يحتوي جسم Coroutine على حلقة لا نهائية تتخللها عمليات yield؛ وبذلك ينتج المولّد القيم عند الطلب دون أن ينتهي. وهذه حالة استخدام أساسية: تسلسلات كسولة ولا نهائية.
local function naturals(start)
return coroutine.wrap(function()
local n = start or 1
while true do
coroutine.yield(n)
n = n + 1
end
end)
end
local gen = naturals(1)
for i = 1, 8 do
io.write(gen() .. " ")
end
print() -- 1 2 3 4 5 6 7 8استخدام Coroutines باعتبارها مهامًا
من أمثلة جدولة المهام الأساسية تخزين Coroutines في قائمة انتظار واستئناف كل منها بدوره. عند تنفيذ Coroutine لعملية yield، تعود إلى قائمة الانتظار. وعند انتهائها، تُزال منها. هذا مجدول تعاوني بسيط.
local tasks = {}
local function spawn(fn)
tasks[#tasks+1] = coroutine.create(fn)
end
local function run()
while #tasks > 0 do
local alive = {}
for _, co in ipairs(tasks) do
coroutine.resume(co)
if coroutine.status(co) ~= "dead" then
alive[#alive+1] = co
end
end
tasks = alive
end
end
spawn(function() for i=1,3 do print("T1:"..i); coroutine.yield() end end)
spawn(function() for i=1,3 do print("T2:"..i); coroutine.yield() end end)
run()ذاكرة الكوروتين
يمتلك كل كوروتين مكدسًا خاصًا به. وقد تكبر المكدسات عند وجود سلاسل استدعاءات عميقة. في سيناريوهات الأداء العالي، تجنّب إنشاء آلاف الكوروتينات النشطة في الوقت نفسه. أعد استخدام الكوروتينات متى أمكن، أو استخدم التجميعات.
-- Coroutine pool concept
local pool = {}
local function getCoroutine(fn)
-- Reuse dead coroutine slots
for i, co in ipairs(pool) do
if coroutine.status(co) == "dead" then
pool[i] = coroutine.create(fn)
return pool[i]
end
end
local co = coroutine.create(fn)
pool[#pool+1] = co
return co
end
print("Pool pattern for coroutine reuse")اختبار سريع
ما الحالة التي يكون فيها الكوروتين مباشرةً بعد coroutine.create(fn)؟
مراجعة: إنشاء الكوروتينات
الملخص:
coroutine.create(fn)← كائن كوروتين؛wrap(fn)← دالة قابلة للاستئناف- الحالات: معلّق ← قيد التشغيل ← معلّق/منتهٍ
- تبدأ العملية أو تُستأنف باستخدام
coroutine.resume(co, ...) - الأخطاء أثناء الاستئناف: false + رسالة الخطأ؛ وينتقل الكوروتين إلى الحالة المنتهية
- مولدات لا نهائية باستخدام
while true do yield() end - تُستخدم لتعدد المهام التعاوني والتسلسلات الكسولة
الأسئلة الشائعة
هل درس «إنشاء البرامج التعاونية» مجاني؟
نعم — نص درس «إنشاء البرامج التعاونية» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Lua Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Lua Academy 4 دروس في المجموع.
ماذا ستتعلم في «إنشاء البرامج التعاونية»؟
أنشئ برامج تعاونية باستخدام coroutine.create وcoroutine.wrap تتمرن على Lua Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Lua Academy؟
لا تُشترط خبرة سابقة. Lua Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «إنشاء البرامج التعاونية»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Lua Academy هذا؟
نعم. كل درس في Lua Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- إنشاء البرامج التعاونية
- resume وyield
- حالة البرنامج التعاوني
- نمط المنتج والمستهلك