Programming Basics SQL HTML CSS JavaScript React Python C++ Java JavaFX Swing Problem Solving English English Conversations Computer Fundamentals Linux Learn Typing

أساسيات البرمجةالإستدعاء الذاتي

  • مفهوم الإستدعاء الذاتي
  • شروط الإستدعاء الذاتي
  • تمارين شاملة حول الإستدعاء الذاتي

مفهوم الإستدعاء الذاتي

الإستدعاء الذاتي ( Recursion ) يقصد به بناء كود يعيد تنفيذ نفسه بنفسه إلى حين إتمام مهمة معينة.

عملياً لتحقيق الإستدعاء الذاتي نقوم ببناء دالة تستدعي نفسها بنفسها و قد ترجع قيمة لنفسها أيضاً، و هذا النوع من الدوال يسمى Recursive Function.

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


فائدة الإستدعاء الذاتي

في حال كانت البيانات المراد التعامل معها موضوعة بشكل شجري ( Tree ) فهنا يكون التعامل معها بأسلوب الإستدعاء الذاتي أمر مناسب جداً و أسهل بكثير من التعامل معها بأساليب أخرى.

أيضاً هناك خوارزميات (أي أساليب في كتابة الكود) تعتمد على الإستدعاء الذاتي بهدف جعل الكود يتنفذ بشكل أسرع، منها خوارزمية مشهورة إسمها Quick Sort يمكن استخدامها لترتيب عناصر المصفوفة بشكل أسرع من الطريقة التقليدية التي تعلمناها سابقاً في درس المصفوفات الأحادية.

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


مثال عملي حول الاستدعاء الذاتي

فرضاً كنت تبني برنامج للحاسوب و أردته يسمح للمستخدم بتبديل كلمة قد تكون موجودة في عدة ملفات بكلمة أخرى و كانت هذا الملفات موضوعة في عدد كبير من المجلدات المتداخلة كما يلي.

في هذه الحالة تستطيع بناء دالة تعمل على النحو التالي:

  • كلما وجدت ملف تقوم بتبديل الكلمة الموجودة فيه.
  • كلما وجدت مجلد تدخل إليه ثم تستدعي نفسها من جديد.
  • حين لا تجد أي مجلد تتوقف عن استدعاء نفسها من جديد.

شروط الإستدعاء الذاتي

أول ما عليك التفكير به عند بناء دالة تستدعي نفسها هو الشرط الذي يجب وضعه لتحديد متى يجب أن تتوقف عن استدعاء نفسها لأنك إن لم تفعل ذلك فإن ذاكرة جهازك ( RAM ) ستمتلئ أو المعالج ( Processor ) سيعمل بأقصى سرعة ممكنة و بلا أي توقف الأمر الذي سيجعل الجهاز يعلّق و لا يستطيع الإستجابة لأي أمر آخر تعطيه له.


الإستدعاء الذاتي المدمر

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

في المثال التالي قمنا بتعريف دالة تظل تعيد استدعاء نفسها إلا ما لا نهاية، الأمر الذي يجعل محرر الكود يعلّق و يتوقف تماماً عن العمل في حال تشغيل الكود.

مثال

function infinite()
{
    infinite();
}


infinite();

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

InternalError: too much recursion

أو قد يظهر لك رسالة أخرى مشابهة في المعنى كما يلي.

RangeError: Maximum call stack size exceeded

جرب الكود


شرح الكود

الفيديو التالي يشرح طريقة عمل الكود خطوة خطوة.



الإستدعاء الذاتي الآمن

في المثال التالي قمنا بتعريف دالة تعيد استدعاء نفسها بنفسها 3 مرات فقط و من ثم تتوقف.

مثال

function count(start, end)
{
    if (start <= end)
    {
        write("counter = " + start + "\n");
        count(start + 1, end);
    }
}


count(1, 3);

سنحصل على النتيجة التالية عند التشغيل.

counter = 1
counter = 2
counter = 3

جرب الكود


شرح الكود

الفيديو التالي يشرح طريقة عمل الكود خطوة خطوة.

تمارين شاملة حول الإستدعاء الذاتي


التمرين الأول

أكتب دالة تستدعي نفسها إسمها countRecusively عند استدعاءها تعطيها عدد صحيح أكبر من 1 فتقوم بطباعة جميع الأعداد الصحيحة الموجودة من هذا العدد وصولاً إلى 1 بشكل تنازلي.

بعدها قم باستدعاء الدالة countRecursively() لتجربتها.

الحل و التفسير


التمرين الثاني

أكتب دالة تستدعي نفسها إسمها factorial عند استدعاءها تعطيها عدد صحيح أكبر أو يساوي 0 فترجع لك قيمة العاملي لهذا العدد.

بعدها قم باستدعاء الدالة factorial() لتجربتها.

الحل و التفسير


التمرين الثالث

أكتب دالة تستدعي نفسها إسمها sum عند استدعاءها تعطيها عدد صحيح أكبر من 0 فترجع لك مجموع الأعداد من هذا العدد إلى 0.

بعدها قم باستدعاء الدالة sum() لتجربتها.

الحل و التفسير