الدالة error()
ارفع الأخطاء باستخدام error() وافهم مستويات الأخطاء ورسائلها
الدالة error() درس مجاني في Lua Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Lua Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Lua Academy 4 دروس في المجموع.
رفع الأخطاء
ترفع error(message, level) خطأً في Lua. ويتوقف التنفيذ وينتقل الخطأ إلى أعلى مكدس الاستدعاءات حتى تلتقطه pcall أو xpcall، أو حتى ينهي البرنامج. ويمكن أن تكون الرسالة أي قيمة، مثل سلسلة نصية أو جدول أو عدد.
local function divide(a, b)
if b == 0 then
error("division by zero")
end
return a / b
end
print(divide(10, 2)) -- 5.0
-- divide(10, 0) -- ERROR: division by zeroمستويات الأخطاء
تتحكم الوسيطة الثانية في error() في الموضع الذي يُبلّغ فيه عن الخطأ. يشير المستوى 1 (الافتراضي) إلى استدعاء error() نفسه. ويشير المستوى 2 إلى المستدعي. أما المستوى 0 فلا يضيف معلومات عن الموضع. استخدموا المستوى 2 في دوال المكتبات لتحميل المسؤولية على كود المستخدم.
local function assertPositive(n, name)
if n <= 0 then
error((name or "value") .. " must be positive, got " .. n, 2)
-- level 2: blame the caller, not this function
end
return n
end
local function compute(x)
assertPositive(x, "x") -- error points here if x <= 0
return math.sqrt(x)
end
compute(-5) -- error: "x must be positive, got -5" at compute() callالأخطاء باستخدام كائنات الجدول
يتيح تمرير جدول كقيمة للخطأ للمستدعين فحص معلومات خطأ مهيكلة، مثل رمز الخطأ والرسالة والسياق. وهذا أكثر إفادة من سلسلة نصية بسيطة، كما يتيح معالجة الأخطاء برمجيًا.
local function openDB(host, port)
if port < 1 or port > 65535 then
error({code="INVALID_PORT", port=port,
msg="port out of range: " .. port})
end
-- ... connect
return {host=host, port=port}
end
local ok, err = pcall(openDB, "localhost", -1)
if not ok and type(err) == "table" then
print("Code:", err.code) -- INVALID_PORT
print("Port:", err.port) -- -1
print("Msg:", err.msg)
endassert() كاختصار نحوي
يعادل assert(v, msg) التعبير if not v then error(msg, 2) end; return v, .... وهو أسلوب اصطلاحي للتحقق من الشروط المسبقة. وإذا كانت قيمة v صحيحة، فتعيد assert جميع وسائطها (وهو أمر مفيد لتسلسل الاستدعاءات).
local function sqrt(n)
assert(type(n) == "number", "expected number, got " .. type(n))
assert(n >= 0, "sqrt of negative: " .. n)
return math.sqrt(n)
end
print(sqrt(16)) -- 4.0
print(sqrt(2)) -- 1.4142...
-- sqrt("hi") -- ERROR: expected number, got stringerror() مقابل return nil,err
هناك اصطلاحان للإشارة إلى الفشل: error() (أسلوب الاستثناءات) أو return nil, msg (الأسلوب الوظيفي). استخدموا error() للظروف غير المتوقعة حقًا، مثل أخطاء البرمجة أو انتهاك العقود. واستخدموا nil, msg لحالات الفشل المتوقعة، مثل عدم العثور على ملف أو انتهاء مهلة الشبكة.
-- Exception style (programming error)
local function mustExist(t, key)
local v = t[key]
if v == nil then error("required key missing: " .. key, 2) end
return v
end
-- Functional style (expected failure)
local function findUser(id)
-- ... database query
return nil, "user not found" -- expected: user may not exist
endالأخطاء في أساليب التحويل
يمكن رفع الأخطاء داخل أساليب التحويل. فإذا حدث خطأ في أسلوب تحويل، فإنه ينتقل إلى الكود الذي سبّب العملية (مثل تعبير حسابي). احرصوا دائمًا على التحقق من المدخلات غير الصالحة داخل أساليب التحويل.
local SafeDiv = {}
SafeDiv.__index = SafeDiv
SafeDiv.__div = function(a, b)
if b.value == 0 then
error("SafeDiv: division by zero", 2)
end
return SafeDiv.new(a.value / b.value)
end
function SafeDiv.new(v)
return setmetatable({value=v}, SafeDiv)
end
local a = SafeDiv.new(10)
local b = SafeDiv.new(0)
local ok, err = pcall(function() return a / b end)
print(ok, err)أنواع الأخطاء المخصّصة
أنشئ دالة مساعدة لبناء كائنات أخطاء ذات أنواع محددة. أدرج وسمًا للنوع حتى يتمكن المستدعون من التمييز بين أنواع الأخطاء المختلفة ومعالجة كل منها بطريقة مناسبة.
local function newError(kind, msg, extra)
return setmetatable(
{kind=kind, message=msg, extra=extra},
{__tostring = function(e)
return "[" .. e.kind .. "] " .. e.message
end}
)
end
local E = {
notFound = function(name) return newError("NOT_FOUND","not found: "..name) end,
badInput = function(msg) return newError("BAD_INPUT", msg) end,
}
local ok, err = pcall(error, E.notFound("config.json"))
if not ok then print(err.kind, err.message) endانتشار الأخطاء
عندما تستدعي دالةٌ دالةً أخرى وتحدث فيها مشكلة، ينتشر الخطأ تلقائيًا صعودًا عبر مكدس الاستدعاءات. لا تحتاج إلى إعادة رفع الخطأ — يكفي ألا تلتقطه. لا تلتقط الأخطاء إلا في المستوى الذي يمكنك فيه معالجتها أو الإبلاغ عنها بشكل مفيد.
local function step3() error("step3 failed") end
local function step2() step3() end
local function step1() step2() end
local ok, err = pcall(step1)
if not ok then
-- err includes the source location
print("Caught at top level:", err)
end
-- Error: input:1: step3 failedتتبّع المكدس باستخدام debug.traceback
يعطي استدعاء error() العادي سطرًا واحدًا من السياق. للحصول على تتبّع كامل للمكدس، استخدم debug.traceback(msg) كقيمة للخطأ. يُجرى ذلك عادةً في معالج xpcall.
local function buggy()
local t = nil
return t.field -- nil indexing: error
end
local ok, err = xpcall(buggy, function(e)
return debug.traceback(e, 2) -- full stack trace
end)
if not ok then
print(err) -- full traceback
endإعادة رفع الأخطاء
قد تلتقط الخطأ أحيانًا لإضافة سياق، ثم تعيد رفعه. استخدم error(err, 0) (المستوى 0) عند إعادة رفع خطأ نصي لتجنب إضافة بادئة موقع أخرى إلى رسالة منسّقة مسبقًا.
local function loadAndParse(path)
local ok, err = pcall(function()
local f = io.open(path, "r")
if not f then error("cannot open: " .. path) end
local content = f:read("a")
f:close()
return content
end)
if not ok then
error("loadAndParse failed: " .. err, 0) -- re-raise with context
end
end
local ok2, msg = pcall(loadAndParse, "missing.txt")
print(ok2, msg)تحقق سريع
ماذا يعني المستوى 2 في error("msg", 2)؟
مراجعة: error()
الملخص:
error(msg, level)— رفع الخطأ؛ المستوى 2 ينسب الخطأ إلى المستدعي- استخدم الجداول للأخطاء المنظّمة التي تتضمن النوع والسياق
assert(v, msg)— أسلوب اصطلاحي للتحقق من الشروط المسبقة- استخدم
error()للأخطاء البرمجية؛ وأعد nil+err عند حالات الفشل المتوقعة - أعد رفع الخطأ باستخدام
error(err, 0)للحفاظ على تنسيق الرسالة
الأسئلة الشائعة
هل درس «الدالة error()» مجاني؟
نعم — نص درس «الدالة error()» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Lua Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Lua Academy 4 دروس في المجموع.
ماذا ستتعلم في «الدالة error()»؟
ارفع الأخطاء باستخدام error() وافهم مستويات الأخطاء ورسائلها تتمرن على Lua Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Lua Academy؟
لا تُشترط خبرة سابقة. Lua Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «الدالة error()»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Lua Academy هذا؟
نعم. كل درس في Lua Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.