الدرس 9 من 10
الأخطاء والتقاطها
- 13 دقيقة
- 6 فحوص
- 3 تلميحات
- إلى المطلوب
هدف الدرس
رمي الخطأ بـ error والتقاطه بـ pcall وإرجاع nil مع رسالة
الشرح
في Lua طريقتان للتعامل مع الفشل. الأولى للفشل المتوقّع، كلاعب يحاول الشراء وذهبه لا يكفي، فالدالة هنا لا تتوقّف بخطأ، بل تُرجع nil ومعها رسالة: return nil, "لا يكفي الذهب"، ومن يستدعيها يفحص النتيجة: local left, err = withdraw(gold, 30) ثم if not left then print(err) end. وبهذه الطريقة تعمل io.open في المكتبة القياسية.
والثانية للخلل الذي لا ينبغي أن يحدث أصلًا، كضرر سالب يصل من كود فيه خطأ، فـ error("ضرر غير صالح") توقف التنفيذ وتنتقل إلى الدالة التي استدعتها، ثم إلى التي قبلها، حتى يلتقطها أحد، وإلا أوقفت السكربت كله. وفي خادم لعبة يعني هذا أن حدثًا واحدًا فيه خطأ يوقف كل ما بعده.
وتلتقط الخطأ بـ pcall(f, ...)، فهي تستدعي f بالوسائط، فإن نجحت أرجعت true ومعها النتائج، وإن رمت خطأً أرجعت false ورسالة الخطأ. وxpcall(f, handler, ...) مثلها، لكنها تمرّر الخطأ أوّلًا إلى handler، مثل debug.traceback التي تخبرك أين وقع. والخطأ الشائع أن تكتب pcall(damage(100, -5))، لأن damage تُستدعى هنا قبل أن تصل إلى pcall، فلا يُلتقط شيء.
المطلوب
اكتب withdraw(gold, amount) التي تُرجع الباقي، أو nil ورسالة إن كان amount أكبر من gold. ثم اكتب damage(hp, amount) التي ترمي خطأً بـ error إن كان amount سالبًا، وإلا أرجعت الصحّة بعد الضرر دون أن تنزل تحت الصفر. وأخيرًا اكتب safeDamage(hp, amount) التي تستدعي damage عبر pcall، فتُرجع النتيجة إن نجحت، أو nil ورسالة الخطأ إن فشلت.
الفحوص
6 فحوص- الدالة withdraw تُرجع الباقي
- عند نقص الذهب تُرجع nil ورسالة
- الدالة damage تُنقص الصحّة ولا تنزل تحت الصفر
- الدالة damage ترمي خطأً عند الضرر السالب
- الدالة safeDamage تُرجع الصحّة الجديدة
- الدالة safeDamage تحوّل الخطأ إلى nil ورسالة دون أن ترميه