تعلّم البرمجة بلغة كوتلن (21): الفرق بين Expression و Statement

تعلّم البرمجة بلغة كوتلن (21): الفرق بين Expression و Statement
أستمع الى المقال

استعرضنا سريعًا الـ Statements والـ Expressions، في درس كتلة تعبير if الشرطية. في هذا الدرس، سنتحدث عن الفرق بين المصطلحين بتفصيل أكبر. بالإضافة إلى استعراض بعض التعبيرات في لغة كوتلن، حيث معظم أجزاء الشفرة تعيد قيمة ما.

الفرق بين Statements و Expressions:

الجمل البرمجية Statements والتعبيرات Expressions، هي أصغر أجزاء الشفرات البرمجية المكونة للتطبيقات والبرامج في معظم لغات البرمجة. وفي لغة البرمجة كوتلن، أغلب أجزاء الشفرة، عبارة عن تعبيرات Expressions تعيد قيمة.

لا ينتج عن الـ Statement  نتيجة أو قيمة معينة بعد انتهاء تنفيذها. أي بمعنى، لا نستطيع إسناد Statement إلى متغير مثلاً، أو وضعها مباشرة في دالة الطباعة ()println. لأنه لعدم وجود قيمة عائدة منها بعد تنفيذها، لن تستطيع دالة الطباعة طباعة أي شيء، وسينتج خطأ يوقف تنفيذ البرنامج بالكامل.

وبالرغم من أن الـ Statements لا تنتج قيمة، ولكننا نحتاجها في الشفرة البرمجية فقط لتأثيرها الجانبي.

أما ال Expressions، ينتج عنها دائمًا قيمة من نوع بيانات معين. فأي تعبير نستخدمه في الشفرة، يعود لنا بقيمة معينة. يمكننا استخدام هذه القيمة سواء بإسنادها في متغير، أو طباعتها مباشرة بوضعها في دالة الطباعة، أو عدم استخدامها إطلاقاً.

عناصر ذات مستوى أعلى Top-Level Element:

تعتبر الـ Statements، عناصر ذات مستوى أعلى Top-Level داخل شفرتنا. وهذا يعني، أنه إذا وضعناها داخل دالة مثلاً، لن نستطيع وضعها داخل جزء آخر من شفرة الدالة. عكس Expressions التي يمكن وضعها داخل Statements وداخل تعبيرات أخرى.

أمثلة على الـ Statements في شفرة كوتلن:

عمليات الإسناد:

عمليات الإسناد عبارة عن جمل برمجية Statements لا تنتج قيمة. فإذا حاولنا فعل التالي:

لن يتم بناء الشفرة من مترجم كوتلن من الأساس، مظهرًا الخطأ التالي:

Expecting an expression

يتوقع إضافة تعبير

أو بطريقة أوضح:

Assignments are not expressions, and only expressions are allowed in this context

عمليات الإسناد ليست تعابير، يسمح فقط باستخدام التعابير في هذا السياق.

ويمكن أن يظهر الخطأين كما نرى في الصورة التالية من برنامج IntelliJ IDEA:

حلقة التكرار for:

تعتبر حلقة for، من أهم الكتل البرمجية التي نستخدمها في كوتلن. لا تنتج هذه الحلقة قيمة معينة بعد انتهاء عملها. هي فقط تقوم بالدوران على عناصر مجموعة معينة من القيم مرتبة بشكل ما. لأننا نريد استخدام عناصر هذه المجموعة من القيم، في تعبيرات أو أي شيء آخر داخل كتلة الحلقة نفسها، أو لتغيير قيمة متغير خارج الحلقة.

كمثال، إذا كان لدينا الشفرة التالية:

حاولنا في الشفرة أعلاه، إسناد القيمة الناتجة من حلقة for، إلى متغير أسميناه loop. ولأنه ليس هناك قيمة تنتج من حلقة for، سيوقف مترجم كوتلن تنفيذ البرنامج أعلاه مظهراً خطأ، كما نرى الصورة التالية من برنامج IntelliJ IDEA:

هذا بالرغم من أن الدالة ()println داخل حلقة الـ for عبارة عن تعبير وتعود بقيمة من نوع Unit بعد إنتهاء عملها، إلا أن حلقة for نفسها لا تعيد قيمة أي شيء، لذا من غير المسموح إسنادها إلى متغير.

في واقع الأمر، ليس من مهام الحلقة for إعادة قيمة، نحن نستخدمها، لتأثيرها غير المباشر على شفرتنا في محيطها الذي توجد به، كأن نضع تعابير Expressions بين قوسيها المعقوفين.

أمثلة على الـ Expressions في شفرة كوتلن:

استدعاء الدوال:

أي استدعاء لدالة في كوتلن، هو عبارة عن تعبير Expression ينتج عنه قيمة. كما رأينا في درس الدوال، أن كل الدوال في كوتلن تعيد قيمة من نوع بيانات ما. سواء وضعنا نوع القيمة ReturnType هذا صراحة، ثم نعيد النتيجة باستخدام كلمة return. أو استخدمنا علامة الإسناد (=) وتركنا كوتلن تستنتج بنفسها نوع بيانات القيمة من التعبير يمين الدالة. مثل:

أو إسناد قيمة من تعبير معين إلى الدالة، وستعيد الدالة القيمة النهائية لهذا التعبير. مثل:

وعند استدعاء دالة ()sum، سيكون هناك قيمة ناتجة من الاستدعاء وهي نتيجة جمع المتغيرات الأربع:  a + b + c + d. بالتالي، يمكننا إسناد الدالة إلى متغير مباشرة أو وضعها في دالة الطباعة ()prinln، كالتالي:

ستكون نتيجة طباعة قيمة المتغير numbersSum العدد 22. وذلك لأن المتغير أصبح يُمثل القيمة العائدة من الدالة، والتي أخذتها الدالة من التعبير a + b + c + d على يمينها. وسيتم طباعة العدد 22 أيضًا، عند وضع الدالة ()sum مباشرةً في دالة الطباعة.

إرجاع القيمة Unit:

قد نحتاج إلى دالة لا نريد منها إعادة قيمة معينة. فمثلًا إذا أردنا إنشاء دالة كل عملها هو طباعة جملة فقط، كالتالي:

ستكون قيمة الإرجاع من دالتنا ()greeting، هي قيمة الإرجاع من التعبير يمين علامة الإسناد، أي القيمة العائدة من دالة ()println. ودالة ()println من مكتبة كوتلن تعيد القيمة Unit. وهو نوع خاص نضعه للدالة إذا لم نريد منها إعادة قيمة. فكما قلنا سابقًا، كل الدوال في كوتلن تعيد قيمة، لذلك يعتبر استدعاء الدوال تعبير Expression.

عند استدعاء دالة ()greeting فقط، ستتم طباعة جملة Hello Kotlin. ولكن، عند وضعها في دالة ()println، سيتم طباعة الجملة، بالإضافة للقيمة العائدة من ()greeting نفسها. وهي قيمة من نوع Unit، كما يظهر في الصورة التالية:

التعبير الشرطي if:

كما شرحنا في درس كتلة التعبير الشرطي if، عكس الكثير من لغات البرمجة، مثل: جافا وغيرها، تعتبر كتلة if تعبير Expression وليس جملة برمجية Statement. يمكن لـ if في لغة كوتلن، أن تعيد قيم كل أنواع البيانات المتوفرة في كوتلن، أو خلط نوعين أو أكثر وإعادة قيمة أحدهما حسب تحقق الشرط. 

لتوضيح ذلك أكثر، فلننظر إلى الشفرة التالية:

أعلنا عن متغير أسميناه ifExp1 وأسندنا له القيمة العائدة من if، والتي ستكون العدد 13 بما أن الشرط 9 < 10 صحيح true. ولأن المتغير ifExp1 أصبح الآن يحمل القيمة 13، وهي من النوع Int، لذا سيكون نوع بياناته Int. وبالطبع ليس علينا وضع النوع للمتغير صراحةً، لأن كوتلن ستستنتج ذلك من القيمة العائدة من كتلة if.

في المتغير الثاني ifExp2 وضعنا النوع Any صراحةً لأن القيمة العائدة من كتلة if قد تكون عدد Int أو نص String. والنوع Any، هو النوع الأب لكل أنواع البيانات في كوتلن. هذا يعني، أن المتغير الذي يحمل النوع Any، يمكننا أن نسند له أي نوع من الأنواع الأخرى.

ولأن الرقم 11 لايشمله النطاق من 1 إلى 10، بالتالي الشرط (11in 1..10) غير صحيح false، لذا سيتم تخطي كتلة if والذهاب إلى كتلة else وإسناد الجملة النصية في داخلها إلى المتغير ifExp2.

في المتغير الثالث ifExp3، بما أن الحرف a يخزن في الذاكرة برقم أقل من رقم الحرف b (تحدثنا عن ذلك في الدرس 19)، إذًا الشرط (‘a’ < ‘b’) صحيح true. ستعمل دالة ()println على طباعة الجملة: a is smaller than b أولًا، ثم ستعيد القيمة Unit. ستأخذ كتلة if القيمة Unit وتسندها إلى المتغير ifExp3.

قبل طباعة قيم المتغيرات الثلاث، نجد أن المتغيرات أصبحت تحمل القيم التالية:

ifExp2 = 13

ifExp2 = “Number 11 not in the range from 1 to 10

ifExp3 = Unit

والآن عند تنفيذ البرنامج، سنجد أن هناك طباعة جملة سابقة وهي التي تم تنفيذها في كتلة if التابعة للمتغير ifExp3، ومن ثم تنفيذ دوال الطباعة الثلاث في آخر البرنامج.

لتكون النتيجة الكاملة للبرنامج كما تُظهره الصورة التالية من برنامج IntelliJ IDEA:

عوامل الزيادة (++) والنقصان (–):

تعتبر هذه العوامل، تعبيرات Expressions. وتستخدم مع المتغيرات لإنقاص أو زيادة قيمتها بواحد. كمثال، إذا كان لدينا متغير وأسندنا له رقم معين، ثم أردنا زيادة قيمته بواحد وطباعة القيمة الجديدة، كالتالي:

سنجد أن نتيجة الطباعة هي الرقم 0، وهي قيمة المتغير x عند الإعلان عنه. بالرغم من أننا استخدمنا عامل الزيادة (++). بالفعل تم زيادة قيمة x بواحد لتصبح 1. ولكن عند استخدام العامل (++) يمين المتغير، هذا التعبير سيعيد قيمة المتغير قبل الزيادة، ومن ثم يزيد قيمة المتغير. وكل ما يهم دالة ()println هو النتيجة العائدة من التعبير. 

إذًا لجعل التعبير يعيد قيمة المتغير بعد زيادة قيمته، سنضع العامل (++) يسار المتغير x، كالتالي:

في هذه المرة، سيتم طباعة الرقم 1. هذا لأن التعبير (x++) أعاد النتيجة بعد الزيادة. وبنفس الطريقة، سنتعامل مع التعبير الذي يستخدم عامل النقصان (–)، والذي يعمل على إنقاص قيمة المتغير بواحد.

هذا الدرس هو جزء من سلسلة تعليم مبادئ البرمجة بلغة كوتلن. لمُتابعة الدروس منذ البداية ومُشاهدة فهرس المحتويات يمكنك الانتقال إلى الدرس الأول من هنا.

هل أعجبك المحتوى وتريد المزيد منه يصل إلى صندوق بريدك الإلكتروني بشكلٍ دوري؟
انضم إلى قائمة من يقدّرون محتوى إكسڤار واشترك بنشرتنا البريدية.