الاستخدام مع Option وFuture
التسلسل المونادي
الاستخدام مع Option وFuture درس مجاني في Scala for Backend Engineering & Functional Programming على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Scala for Backend Engineering & Functional Programming، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Scala for Backend Engineering & Functional Programming 4 دروس في المجموع.
ما وراء المجموعات
لا تقتصر تعبيرات for-comprehension على القوائم. إذ يمكن استخدام أي نوع يوفر map وflatMap، بما في ذلك Option وEither وTry وFuture. ويُسمى هذا التسلسل المونادي.
object Main {
def main(args: Array[String]): Unit = {
val sum = for {
a <- Some(10)
b <- Some(20)
} yield a + b
println(sum)
}
}يتوقف Option مبكرًا عند None
مع Option، لا ينتج التعبير نتيجة إلا إذا كان كل مولّد هو Some. وإذا كان أي مولّد هو None، تصبح النتيجة كلها None وتُتخطى الخطوات اللاحقة.
object Main {
def main(args: Array[String]): Unit = {
val ok = for {
a <- Some(2)
b <- Some(3)
} yield a * b
val missing = for {
a <- Some(2)
b <- None: Option[Int]
} yield a * b
println(ok)
println(missing)
}
}تسلسل عمليات البحث الاختيارية
من الأنماط الشائعة البحث عن مفاتيح في Map، حيث يعيد كل بحث قيمة من نوع Option. ينتج تعبير for-comprehension قيمة فقط إذا نجحت كل عمليات البحث.
object Main {
def main(args: Array[String]): Unit = {
val prices = Map("apple" -> 3, "bread" -> 5)
val total = for {
a <- prices.get("apple")
b <- prices.get("bread")
} yield a + b
println(total)
val missing = for {
a <- prices.get("apple")
c <- prices.get("milk")
} yield a + c
println(missing)
}
}لماذا يتفوق هذا على if-else المتداخل
من دون تعبيرات for-comprehension، ستحتاجون إلى تداخل مطابقة الأنماط أو فحوصات القيم الفارغة. أما الصيغة المونادية فتسطّح ذلك الهرم إلى تسلسل خطي واضح.
object Main {
def parse(s: String): Option[Int] = s.toIntOption
def main(args: Array[String]): Unit = {
val result = for {
x <- parse("40")
y <- parse("2")
} yield x + y
println(result)
}
}تعمل الحراس مع Option أيضًا
يحوّل الحارس داخل تعبير Option قيمةً إلى None عند فشل الشرط، فيعمل بمثابة تحقق مضمّن.
object Main {
def main(args: Array[String]): Unit = {
def validate(age: Int): Option[Int] =
for {
a <- Some(age)
if a >= 18
} yield a
println(validate(25))
println(validate(15))
}
}تقديم Future
يمثل Future قيمة ستصبح متاحة لاحقًا. وكما هو الحال مع Option، فإنه يوفّر map وflatMap، ولذلك تسلسل تعبيرات for-comprehension الخطوات غير المتزامنة.
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration._
object Main {
def main(args: Array[String]): Unit = {
val f = for {
a <- Future(10)
b <- Future(20)
} yield a + b
println(Await.result(f, 2.seconds))
}
}تعمل Futures بالتسلسل هنا
عندما يعتمد مولّد على مولّد آخر داخل تعبير for-comprehension، تعمل Futures بالتسلسل، لأن كل flatMap ينتظر نتيجة الخطوة السابقة.
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration._
object Main {
def main(args: Array[String]): Unit = {
val f = for {
a <- Future(5)
b <- Future(a * 2)
} yield a + b
println(Await.result(f, 2.seconds))
}
}تشغيل Futures بالتوازي
لتشغيل Futures بالتوازي، ابدؤوا تشغيلها قبل تعبير for-comprehension، ثم اجمعوا النتائج. عندئذٍ يتداخل العمل المستقل بدلًا من الانتظار.
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration._
object Main {
def main(args: Array[String]): Unit = {
val fa = Future(100)
val fb = Future(200)
val combined = for {
a <- fa
b <- fb
} yield a + b
println(Await.result(combined, 2.seconds))
}
}Either لأخطاء أكثر تفصيلًا
يحمل Either[E, A] قيمة خطأ عند الفشل. وفي تعبير for-comprehension، يتوقف التنفيذ عند أول Left وتُعاد هذه القيمة.
object Main {
def parse(s: String): Either[String, Int] =
s.toIntOption.toRight(s"not a number: $s")
def main(args: Array[String]): Unit = {
val good = for { a <- parse("3"); b <- parse("4") } yield a + b
val bad = for { a <- parse("3"); b <- parse("x") } yield a + b
println(good)
println(bad)
}
}البنية نفسها مع أنواع متعددة
لاحظوا أن تعبير for-comprehension يبدو متطابقًا سواء استخدمتم Option أو Either أو Try أو Future. والاختلاف الوحيد هو دلالات الفشل. وتكمن قوة التسلسل المونادي في هذا التوحيد.
import scala.util.Try
object Main {
def main(args: Array[String]): Unit = {
val result = for {
a <- Try("21".toInt)
b <- Try("2".toInt)
} yield a * b
println(result)
}
}لا يُسمح بمزج الأنواع
يجب أن تكون كل المولّدات في تعبير for-comprehension واحد من الموناد نفسه. لا يمكنكم مزج مولّد Option مع مولّد Future مباشرةً؛ بل حوّلوا أحدهما أولًا، مثلًا باستخدام Future.fromTry، أو غلّفوا Option.
object Main {
def main(args: Array[String]): Unit = {
// Convert the Option to keep types consistent
val maybe: Option[Int] = Some(7)
val result = for {
a <- maybe
b <- maybe.map(_ + 1)
} yield a + b
println(result)
}
}تحقق سريع
في تعبير for-comprehension من نوع Option، ماذا يحدث إذا أعاد أحد المولّدات None؟
مراجعة
لقد تعلمتم التسلسل المونادي باستخدام تعبيرات for-comprehension:
- يعمل مع أي نوع يوفّر
mapوflatMap - يتوقف
Optionمبكرًا عندNone - يتوقف
EitherوTryعند الفشل مع الاحتفاظ بمعلومات الخطأ - يسلسل
Futureالخطوات غير المتزامنة؛ ابدؤوها مبكرًا لتحقيق التوازي - يجب أن تشترك كل المولّدات في نوع الموناد نفسه
تعلم Scala مع معلم ذكاء اصطناعي — مجانًا
اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.
- الدورات
- 39
- الدروس
- 143
الأسئلة الشائعة
هل درس «الاستخدام مع Option وFuture» مجاني؟
نعم — نص درس «الاستخدام مع Option وFuture» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Scala for Backend Engineering & Functional Programming، انتقل إلى CoddyKit PRO. تتضمن دورة Scala for Backend Engineering & Functional Programming 4 دروس في المجموع.
ماذا ستتعلم في «الاستخدام مع Option وFuture»؟
التسلسل المونادي تتمرن على Scala for Backend Engineering & Functional Programming مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Scala for Backend Engineering & Functional Programming؟
لا تُشترط خبرة سابقة. Scala for Backend Engineering & Functional Programming على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «الاستخدام مع Option وFuture»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Scala for Backend Engineering & Functional Programming هذا؟
نعم. كل درس في Scala for Backend Engineering & Functional Programming يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- إزالة السكر النحوي من for
- التصفية باستخدام if
- مولدات متعددة
- الاستخدام مع Option وFuture