كتابة دوال متينة باستخدام stop() وwarning()
أطلق شروطًا مخصّصة من داخل دوالك الخاصة.
كتابة دوال متينة باستخدام stop() وwarning() درس مجاني في R Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في R Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة R Academy 4 دروس في المجموع.
أهمية التحقق من المدخلات
تتحقق الدوال الدفاعية من مدخلاتها وتفشل بوضوح مع أخطاء مفيدة بدلًا من إنتاج نتائج خاطئة بصمت. فالدالة التي تكتشف المدخلات غير الصالحة عند الحد الفاصل أسهل بكثير في تصحيحها من دالة تمرر بيانات تالفة عبر مسار المعالجة.
# Without validation: wrong result, no error
bad_mean <- function(x) sum(x) / length(x)
bad_mean('hello') # no error, just NA
# With validation: clear error
good_mean <- function(x) {
if (!is.numeric(x)) stop('x must be numeric')
sum(x) / length(x)
}
tryCatch(good_mean('hello'), error = function(e) cat(e$message, '\n'))رسائل أخطاء مفيدة
يصعب تصحيح الأخطاء العامة مثل stop('bad input'). استخدموا paste0() أو sprintf() داخل stop() لتضمين القيمة الفعلية والنوع المتوقع في الرسالة. ويوفر ذلك وقتًا عند تتبع الأخطاء في مسارات المعالجة.
check_numeric <- function(x, arg_name = 'x') {
if (!is.numeric(x)) {
stop(sprintf(
"'%s' must be numeric, but got class '%s'",
arg_name, class(x)
))
}
}
tryCatch(check_numeric('abc', 'score'),
error = function(e) cat(e$message, '\n'))التحقق من الطول والنطاق
تشمل عمليات التحقق الشائعة التأكد من أن المتجه غير فارغ (length(x) == 0)، وأن قيمة مفردة تقع ضمن نطاق معين، أو أن إطار البيانات يحتوي على الأعمدة المتوقعة. وينبغي أن تكون لكل عملية تحقق رسالة خطأ مخصصة لها.
validate_prob <- function(p) {
if (!is.numeric(p)) stop(paste0('p must be numeric, got: ', class(p)))
if (length(p) != 1) stop(paste0('p must be length 1, got: ', length(p)))
if (p < 0 || p > 1) stop(paste0('p must be in [0,1], got: ', p))
p
}
cat(validate_prob(0.7), '\n')
tryCatch(validate_prob(1.5), error = function(e) cat(e$message, '\n'))استخدام warning() للمشكلات غير القاتلة
استخدموا warning() عندما تتمكن الدالة من إرجاع نتيجة معقولة، لكن ينبغي للمستدعي معرفة حدوث أمر غير معتاد، مثل تحويل قيمة أو تعويض قيمة افتراضية أو اكتشاف مدخل يقع على حدود النطاق.
clamp <- function(x, lo, hi) {
if (any(x < lo)) warning(paste0(sum(x < lo), ' value(s) below lo, clamped'))
if (any(x > hi)) warning(paste0(sum(x > hi), ' value(s) above hi, clamped'))
pmax(lo, pmin(hi, x))
}
result <- clamp(c(2, -5, 7, 100, 4), 0, 10)
cat('Result:', result, '\n')call. = FALSE في stop()
تضيف stop() افتراضيًا البادئة Error in funcname(...): إلى الرسالة. مرروا call. = FALSE لمنع هذه البادئة عندما يكون سياق الاستدعاء واضحًا أو عندما تكون الدالة أداة موجهة للمستخدم.
# With call. = TRUE (default): shows calling function
f1 <- function(x) stop('bad input')
tryCatch(f1(1), error = function(e) cat(conditionMessage(e), '\n'))
# With call. = FALSE: cleaner message
f2 <- function(x) stop('bad input', call. = FALSE)
tryCatch(f2(1), error = function(e) cat(conditionMessage(e), '\n'))فئات شروط مخصصة لـ stop()
أنشئوا فئة خطأ مخصصة باستخدام structure() حتى يتمكن المستدعون من التقاط أخطاء دالتكم فقط دون التقاط جميع الأخطاء. وهذه هي الطريقة الاحترافية لكتابة أخطاء على مستوى الحزم.
value_error <- function(msg, call = sys.call(-1)) {
structure(
class = c('value_error', 'error', 'condition'),
list(message = msg, call = call)
)
}
check_positive <- function(x) {
if (x <= 0) stop(value_error(paste0('Expected positive, got: ', x)))
x
}
tryCatch(check_positive(-3),
value_error = function(e) cat('ValueError:', e$message, '\n'),
error = function(e) cat('Other error:', e$message, '\n'))التحقق من أعمدة إطار البيانات
عندما تتوقع الدالة إطار بيانات، تحققوا من وجود الأعمدة المطلوبة قبل استخدامها. استخدموا %in% للتحقق من أسماء الأعمدة وsetdiff() للإبلاغ عن الأعمدة المفقودة.
require_cols <- function(df, cols) {
missing <- setdiff(cols, names(df))
if (length(missing) > 0) {
stop(paste0('Missing columns: ', paste(missing, collapse = ', ')))
}
invisible(df)
}
df <- data.frame(x = 1:3, y = 4:6)
tryCatch(
require_cols(df, c('x', 'z', 'w')),
error = function(e) cat(e$message, '\n')
)stopifnot() للتأكيدات الموجزة
تُطلق stopifnot(condition1, condition2, ...) خطأً إذا كانت أي حالة تساوي FALSE. وهي طريقة موجزة لتأكيد الشروط المسبقة في بداية الدالة دون كتابة كتل منفصلة من if (!...) stop(...).
compute_area <- function(width, height) {
stopifnot(
is.numeric(width),
is.numeric(height),
width > 0,
height > 0
)
width * height
}
cat(compute_area(5, 3), '\n')
tryCatch(compute_area(-1, 3), error = function(e) cat(e$message, '\n'))stopifnot() المسمى لرسائل أفضل
في R 4.0+، تستبدل التعبيرات المسماة داخل stopifnot() الرسالة المُنشأة تلقائيًا بالوصف المخصص لكم. استخدموا نص التعبير اسمًا لإنتاج إخفاقات مفيدة.
validate_age <- function(age) {
stopifnot(
'age must be numeric' = is.numeric(age),
'age must be positive' = age > 0,
'age must be under 150' = age < 150
)
invisible(age)
}
tryCatch(validate_age(-5), error = function(e) cat(e$message, '\n'))
tryCatch(validate_age('x'), error = function(e) cat(e$message, '\n'))دمج التحقق ومنطق الأعمال
تفصل الدالة جيدة البنية بين التحقق والمنطق. أجروا التحقق في البداية، ثم نفذوا العملية. يجعل ذلك الدالة أسهل قراءة ويضمن اكتشاف الأخطاء قبل بدء أي حساب.
discount_price <- function(price, pct) {
if (!is.numeric(price) || price <= 0)
stop(paste0('price must be positive numeric, got: ', price))
if (!is.numeric(pct) || pct < 0 || pct > 100)
stop(paste0('pct must be in [0,100], got: ', pct))
if (pct > 50) warning('discount > 50% is unusual')
price * (1 - pct / 100)
}
cat(discount_price(100, 20), '\n')
cat(suppressWarnings(discount_price(100, 60)), '\n')استخدام tryCatch داخل الدوال المساعدة
قد تحتاج الدالة المساعدة أحيانًا إلى معالجة الأخطاء داخليًا وإرجاع قيمة احتياطية بدلًا من تمرير الأخطاء. أحيطوا المنطق الأساسي بـ tryCatch() وأرجعوا قيمة مؤشر متفقًا عليها مثل NA أو NULL عند الفشل.
safe_log <- function(x) {
tryCatch({
if (!is.numeric(x)) stop('not numeric')
if (x <= 0) stop('must be positive')
log(x)
}, error = function(e) {
warning(paste0('safe_log failed for x=', x, ': ', e$message))
NA_real_
})
}
results <- sapply(list(10, -1, 'a', 100), safe_log)
cat(results, '\n')تحقق سريع
ماذا يفعل call. = FALSE عند تمريره إلى stop()؟
الدوال المتينة: أهم النقاط
أهم النقاط حول كتابة دوال متينة:
- تحققوا من المدخلات في البداية، واجعلوا الفشل واضحًا باستخدام رسائل
stop()المفيدة - ضمّنوا القيمة الفعلية في رسائل الخطأ:
paste0('Expected numeric, got: ', class(x)) - استخدموا
warning()للمشكلات غير القاتلة التي يمكن معها استمرار الحساب - يمنع
call. = FALSEبادئة الدالة المستدعية في رسائل الخطأ - استخدموا
stopifnot()للتأكيدات الموجزة، والصيغة المسماة للرسائل المخصصة (R 4.0+) - تتيح فئات الشروط المخصصة للمستدعين التقاط الأخطاء بصورة انتقائية
robust_divide <- function(x, y) {
stopifnot('x must be numeric' = is.numeric(x),
'y must be numeric' = is.numeric(y))
if (y == 0) stop('Division by zero', call. = FALSE)
if (abs(y) < 1e-10) warning('y is very small; result may be inaccurate')
x / y
}
cat(robust_divide(10, 2), '\n')
tryCatch(robust_divide(10, 0), error = function(e) cat(e$message, '\n'))تعلم R مع معلم ذكاء اصطناعي — مجانًا
اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.
- الدورات
- 43
- الدروس
- 159
الأسئلة الشائعة
هل درس «كتابة دوال متينة باستخدام stop() وwarning()» مجاني؟
نعم — نص درس «كتابة دوال متينة باستخدام stop() وwarning()» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة R Academy، انتقل إلى CoddyKit PRO. تتضمن دورة R Academy 4 دروس في المجموع.
ماذا ستتعلم في «كتابة دوال متينة باستخدام stop() وwarning()»؟
أطلق شروطًا مخصّصة من داخل دوالك الخاصة. تتمرن على R Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ R Academy؟
لا تُشترط خبرة سابقة. R Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «كتابة دوال متينة باستخدام stop() وwarning()»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس R Academy هذا؟
نعم. كل درس في R Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- الأخطاء والتحذيرات والرسائل في R
- tryCatch() لاسترداد الأخطاء
- withCallingHandlers() وإعادات التشغيل
- كتابة دوال متينة باستخدام stop() وwarning()