الأساسيات
if في Zero تبدو تقريبًا مثل if في كل لغة من عائلة C، مع قيد ملحوظ واحد: الشرط يجب أن يكون من النوع bool.
الشرط value == 42 من النوع bool لأن == بين قيمتَين من النوع i32 يُعيد bool. كلا الفرعين يحتوي على كتلة من العبارات. أيّ فرع يمكن إغفاله نوعًا ما — else اختيارية — لكن عندما يكونان حاضرَين، يجب أن يكون كلاهما كتلة { ... }.
اشتراط bool
بعض اللغات تسمح بكتابة if value { ... } وتُعامل 0 أو "" أو null كقيم كاذبة (falsy). Zero لا تفعل ذلك. الشرط يجب أن يكون من النوع bool فعليًا.
let count = 0
if count { // خطأ ترجمة: متوقّع bool، تمّ توفير i32
// ...
}
if count == 0 { // صحيح
check world.out.write("nothing to do\n")
}
السبب هو نفسه الذي يسري في بقية اللغة: الصراحة تتفوّق على الضمنية. الوكيل الذي يقرأ الشكل الثاني يعرف بالضبط ما يُتحقَّق منه. الشكل الأول يترك قواعد قيم الصدق ضمنية وتختلف بين اللغات — وZero تختار الخروج من هذه اللعبة.
else و else-if
يعمل فرع else عندما يكون الشرط false:
اسلسل الشروط بـ else if:
if value < 0 {
check world.out.write("negative\n")
} else if value == 0 {
check world.out.write("zero\n")
} else {
check world.out.write("positive\n")
}
else if هي مجرّد else { if ... } بدون الأقواس — دلالات (semantics) واحدة، وبزَيْحَة أقلّ. else الأخيرة اختيارية.
من أين يأتي الشرط
الشرط قد يكون أي شيء يُقيَّم إلى bool:
- ربط
bool:if ok { ... }. - مقارنة:
if value == 42 { ... }أوif x < y { ... }. - تركيب منطقي:
if a && b { ... }أوif pair.left == 1_u8 && pair.right == 2_u8 { ... }. - استدعاء دالة تُعيد
bool:if isReady(world) { ... }.
مقتطف من أمثلة اللغة:
let pair: BytePair = Pair { left: 1_u8, right: 2_u8 }
if pair.left == 1_u8 && pair.right == 2_u8 {
check world.out.write("type alias ok\n")
} else {
check world.out.write("type alias broke\n")
}
&& تختصر المسار كما تتوقّع — إذا كان الطرف الأوّل false، فلن يُقيَّم الطرف الثاني. الأمر نفسه لـ ||.
متى تستخدم match بدلًا من ذلك
سلاسل if/else if جيّدة لقرارات ثنائية أو ثلاثية الاتّجاه، خاصة عندما لا تتشارك الشروط بنية. لكن عندما تتفرّع على متغيِّرات نوع مجموع — choice أو enum — match هي الأداة الصحيحة.
قارن:
// match — شامل، مفحوص من المترجم
match result {
.ok => value { check world.out.write("ok\n") }
.err => message { check world.out.write("err\n") }
}
مقابل:
// if/else على نوع مجموع — مُطوَّل وأسهل في الخطأ
if result.isOk() {
let value = result.unwrap()
check world.out.write("ok\n")
} else {
check world.out.write("err\n")
}
شكل match يجعل تحليل المتغيِّر صريحًا والمترجم سيشتكي إن أُضيف متغيِّر جديد لاحقًا ونسيت معالجته. أمّا شكل if فيُمرّر أي شيء غير ok بصمت إلى فرع else، حتى المتغيِّرات الجديدة التي لم تفكّر فيها قطّ.
قاعدة عملية: if للقيم المنطقية، وmatch للمتغيِّرات.
ملاحظات أسلوبية
اتّفاقات صغيرة تجعل الشيفرة أسهل قراءةً للبشر والوكلاء معًا:
- استخدم الأقواس دومًا حول الجسم. حتى جسم من سطر واحد يدخل في
{ ... }. لا يوجد شكل بدون أقواس لعبارة واحدة. هذا متعمّد — يُبقي الإزاحة موثوقة ويزيل مصدرًا شائعًا للأخطاء في عائلة C. - ضع الفرع الأكثر شيوعًا أوّلًا. القرّاء (والوكلاء) يقرؤون من الأعلى إلى الأسفل.
- فضّل الشروط الإيجابية عندما تكون بنفس الوضوح.
if isReadyأسهل متابعةً منif !notReady، إذا تساوى كل شيء آخر.
التالي: حلقات while
الشروط تُقرّر ماذا يحدث؛ والحلقات تُقرّر كم مرة يحدث. التوثيق التالي يُغطّي حلقات while في Zero، بنية الحلقات الموجودة في مرحلتها المبكّرة من اللغة.
الأسئلة الشائعة
كيف تعمل عبارة if في Zero؟
استخدم if condition { ... } مع عبارة else { ... } اختيارية. الشرط يجب أن يكون من النوع bool — لا تُحوّل Zero الأعداد الصحيحة أو النصوص أو القيم الأخرى تلقائيًا إلى قيمة منطقية. مثلًا: if value == 42 { check world.out.write("yes\n") } else { check world.out.write("no\n") }.
هل لدى Zero عامل ثلاثي؟
تُبقي Zero مساحتها السطحية صغيرة عمدًا وتستخدم كتل if وelse بدلًا من العامل الثلاثي المنفصل condition ? a : b. الأمثلة الرسمية تُفضّل الفروع الصريحة حتى للحالات القصيرة. إذا دعمت اللغة تعبير if-as-expression، توقّع أن تميل Zero إلى ذلك الاتّجاه بدلًا من تقديم صياغة ثانية.
هل يمكن سَلْسَلة if/else if في Zero؟
نعم. اربط الشروط بكتابة else if بين الفروع: if a { ... } else if b { ... } else { ... }. للتفرّع المُفصَّل على choice أو enum، استخدم match بدلًا من ذلك — هو أكثر شمولًا والمترجم يتحقّق من أنك عالجت كل متغيِّر.
لماذا لا تُحوّل Zero القيم تلقائيًا إلى bool؟
فلسفة تصميم Zero هي 'كل شيء صريح'. التحويل الضمني لقيم الصدق — معاملة 0 و"" وnull كـ false — مصدر متكرّر للأخطاء ويصعب على الوكيل الاستدلال عليه بدقّة. اشتراط bool فعلي يجعل قرار التفرّع مرئيًا في المصدر وأسهل للتحقّق آليًا.
متى تستخدم match بدلًا من if/else؟
استخدم match عندما تتفرّع على متغيِّرات choice أو enum. يستطيع المترجم التحقّق من أنك غطّيت كل حالة، وهذا ما لا تستطيع سلاسل if/else if فعله. أبقِ if/else للمسندات المنطقية البسيطة — فحوصات المساواة، والمقارنات، والتفرّعات الثنائية القصيرة.