Arrow Raise DSL: تركيب الأخطاء المعرّفة بالأنواع
استخدم سياق Raise في Arrow والدالة raise() لتركيب تدفقات متعددة الأخطاء بوضوح
Arrow Raise DSL: تركيب الأخطاء المعرّفة بالأنواع درس مجاني في Kotlin Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Kotlin Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Kotlin Academy 4 دروس في المجموع.
محدودية تسلسل Either
يؤدي تسلسل Either باستخدام flatMap إلى لامبدات متداخلة بعمق عند وجود عدة عمليات متتابعة. ويوفر Raise DSL في Arrow (المُقدَّم في Arrow 1.2) صياغةً أنظف على نمط coroutines باستخدام مستقبلات السياق في Kotlin أو دوال الامتداد.
ما هو Raise<E>؟
Raise هو سياق يمكنه رفع خطأ من النوع E وإيقاف التنفيذ فورًا. وتستدعي الدالة التي قد تفشل raise(error) لإيقاف التنفيذ ونشر الخطأ، بطريقة تشبه رمي الاستثناءات ولكن من دون استخدامها.
الباني either { }
ينشئ الباني either { } قيمة Either من كتلة يكون فيها Raise ضمن النطاق. وداخلها، استخدم raise(error) عند الفشل، أو أعد قيمةً ببساطة عند النجاح:
import arrow.core.raise.either
import arrow.core.raise.Raise
fun validateAge(age: Int): Either<String, Int> = either {
if (age < 0) raise("Age cannot be negative")
if (age > 150) raise("Age too large")
age
}bind() — فك تغليف Either داخل either{}
داخل كتلة either { }، استدعِ .bind() على أي قيمة من نوع Either لفك تغليفها. وإذا كانت Left، يرفع bind() الخطأ تلقائيًا ويوقف تنفيذ الكتلة:
fun createUser(name: String, age: Int): Either<String, User> = either {
val validName = validateName(name).bind() // raises if Left
val validAge = validateAge(age).bind() // raises if Left
User(validName, validAge) // only reached if both succeed
}ensure() — التحقق من شرط ضمني
ensure(condition) { error } اختصار لـ if (!condition) raise(error). وهي تحافظ على إيجاز منطق التحقق:
fun validateEmail(email: String): Either<String, String> = either {
ensure(email.contains("@")) { "Email must contain @" }
ensure(email.length <= 255) { "Email too long" }
email
}ensureNotNull() — التحقق من null باستخدام Raise
تفك ensureNotNull(value) { error } تغليف قيمة قابلة لأن تكون null، أو ترفع خطأً إذا كانت null:
fun findUser(id: Long, repo: UserRepo): Either<UserError, User> = either {
ensureNotNull(repo.findById(id)) { UserError.NotFound(id) }
}استخدام Raise مع مستقبلات السياق (Arrow 1.2+)
يمكنك التصريح مباشرةً عن دوال تتطلب سياقًا من نوع Raise، من دون تغليفها داخل either { }:
context(Raise<String>)
fun requirePositive(n: Int): Int {
ensure(n > 0) { "Must be positive" }
return n
}
// Called inside either { }
val result = either { requirePositive(-1) } // Left("Must be positive")تجميع الأخطاء باستخدام zipOrAccumulate
يتوقف Raise افتراضيًا عند أول خطأ. استخدم zipOrAccumulate() لتنفيذ عمليات تحقق متعددة وتجميع جميع الأخطاء في NonEmptyList:
val result: Either<NonEmptyList<String>, User> = either {
zipOrAccumulate(
{ validateName(name).bind() },
{ validateAge(age).bind() }
) { validName, validAge -> User(validName, validAge) }
}recover { } — معالجة أخطاء محددة
استخدم recover { error -> ... } داخل either { } لمعالجة خطأ محدد تم رفعه وتوفير قيمة بديلة، ثم استئناف العملية الحسابية:
val name: String = either {
findUser(0L).bind().name
}.recover { error ->
if (error == UserError.NotFound) "Guest" else raise(error)
}.getOrNull() ?: "Guest"المقارنة بين Raise وتسلسل Either: متى يُستخدم كل منهما
استخدم either { }.bind() للتدفقات الخطية التي تتضمن عدة خطوات متتابعة؛ فهي تُقرأ كالشيفرة الإجرائية مع بقائها نقية. واستخدم تسلسل flatMap للتركيبات القصيرة المؤلفة من خطوتين أو عند التكامل مع مكتبات وظيفية أخرى.
اختبار الدوال المعتمدة على Raise
اختبر الدالة باستدعائها داخل either { } ثم التحقق من النتيجة. وتسهّل مطابِقات Kotest في Arrow، مثل shouldBeLeft() وshouldBeRight()، كتابة التأكيدات بإيجاز:
import arrow.core.shouldBeLeft
import arrow.core.shouldBeRight
@Test
fun `negative age returns Left`() {
validateAge(-1).shouldBeLeft()
}
@Test
fun `valid age returns Right`() {
validateAge(25).shouldBeRight(25)
}تحقق سريع
ماذا يحدث عند استدعاء .bind() على قيمة Either.Left داخل كتلة either { }؟
مراجعة: Arrow Raise DSL
النقاط الأساسية:
- ينشئ
either { }قيمةEitherمن كتلة يكون فيهاRaiseضمن النطاق - يفك
.bind()تغليفEitherويتوقف عندLeft - استخدم
ensure(condition) { error }وensureNotNull(value) { error }لإجراء عمليات تحقق ضمنية - استخدم
zipOrAccumulate()لتجميع عدة أخطاء بدلًا من التوقف عند أول خطأ - تُقرأ الشيفرة كأنها إجرائية مع بقائها وظيفيةً خالصة
الأسئلة الشائعة
هل درس «Arrow Raise DSL: تركيب الأخطاء المعرّفة بالأنواع» مجاني؟
نعم — نص درس «Arrow Raise DSL: تركيب الأخطاء المعرّفة بالأنواع» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Kotlin Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Kotlin Academy 4 دروس في المجموع.
ماذا ستتعلم في «Arrow Raise DSL: تركيب الأخطاء المعرّفة بالأنواع»؟
استخدم سياق Raise في Arrow والدالة raise() لتركيب تدفقات متعددة الأخطاء بوضوح تتمرن على Kotlin Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Kotlin Academy؟
لا تُشترط خبرة سابقة. Kotlin Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «Arrow Raise DSL: تركيب الأخطاء المعرّفة بالأنواع»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Kotlin Academy هذا؟
نعم. كل درس في Kotlin Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- Either : معالجة الأخطاء ذات الأنواع من دون استثناءات
- Arrow Raise DSL: تركيب الأخطاء المعرّفة بالأنواع
- Option وNullable: متى تستخدم كلًّا منهما
- نمذجة المجالات الوظيفية باستخدام الأنواع الأساسية في Arrow