OOZOU
تواصلوا معنا
العودة إلى المدونة

تحسين الاستدعاء الذيلي (Tail Call Optimization) في Kotlin

كيف تستفيدون من الاستدعاء الذاتي (recursion) في Kotlin.

25 يوليو 2017
3 دقائق للقراءة
تحسين الاستدعاء الذيلي (Tail Call Optimization) في Kotlin

بما أن Kotlin لغة متعددة النماذج البرمجية (multi-paradigm)، يمكننا تجنّب استخدام حلقة for واستخدام الاستدعاء الذاتي (recursion) بدلًا منها. في هذه المقالة سأعرض حيلة صغيرة لتطبيق تحسين الاستدعاء الذيلي (TCO) في Kotlin.

تُعرَّف البرمجة الأمرية (Imperative Programming) عادةً بأربعة عناصر:

Sequence, Selection, Iteration, Subroutine

لكن البرمجة الوظيفية (FP) لا تحتوي على مفهومَي Sequence وIteration. فإذا فكّرنا في برنامج لا توجد فيه حلقات تكرار، سنجد أن الأداة الوحيدة المتبقية لنا هي الدالة الاستدعائية. دعوني أكتب دالة استدعائية قصيرة تحسب المضروب (factorial):

fun factorial(num: Double): Double {
        when (num) {
            1.0 ->
                return num
            else ->
                return factorial(num - 1) * num
        }
    }
lang-kotlin

هذا الكود يعمل جيدًا ويعطيكم النتيجة المتوقعة، لكن ماذا لو أخبرتكم أنه قد يسبب لكم مشكلة؟

خطأ StackOverflow

في كل مرة نستدعي فيها دالة، يُنشأ stack frame جديد. لنفترض أنني استدعيت هذه الدالة 50,000 مرة، فسيُنشأ 50,000 frame في الـ stack، وعندما يصل الحجم إلى الحد الأقصى سيظهر هذا الخطأ. إضافة إلى ذلك، فإن أداء هذا الكود سيئ أيضًا.

تحسين الاستدعاء الذيلي

لحل المشكلة، يمكننا تحويل الكود إلى استدعاء ذاتي ذيلي (tail recursion)، أي أن السطر الذي تستدعي فيه الدالة نفسها يجب أن يكون آخر سطر، ويجب ألا تتبعه أي عملية حسابية. على سبيل المثال:

fun myfunc(num : Int = 20): Int {
    if(num == 0){
        return 0
    } else {
        return myfunc()
    }
}
lang-kotlin

الدالة السابقة دالة tail recursion. وإليكم مثالًا آخر ليس tail recursion.

fun notaTailRecursionFunction(num : Int = 20): Int {
        if(num == 0){
            return 0
        } else {
            return notaTailRecursionFunction() + 10
        }
    }
lang-kotlin

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

لنحسّن دالة المضروب:

private fun factorial(num: Double): Double {
        return factorial(num, 1.0)
    }

fun factorial(num: Double, result: Double): Double {
        when (num) {
            0.0 ->
                return result
            else ->
                return factorial(num-1, num * result)
        }
    }
lang-kotlin

كل ما فعلته أنني قسمتها إلى دالتين، وتأكدت من أن كلتيهما تتبع مفهوم الـ tail recursion.

هل هذا كل شيء؟ لا. فكما في Scala مع @tailrec، تحتاجون في Kotlin أيضًا إلى تعريف دالة الـ tail recursion باستخدام tailrec syntax، وإلا ستواجهون المشكلة نفسها.

private fun factorial(num: Double): Double {
        return factorial(num, 1.0)
    }

tailrec fun factorial(num: Double, result: Double): Double {
        when (num) {
            0.0 ->
                return result
            else ->
                return factorial(num-1, num * result)
        }
    }
lang-kotlin

لنشغّل البرنامج ونرى الـ stack frame:

إذن، في كل مرة تريدون فيها استخدام الاستدعاء الذاتي، عليكم مراعاة أمرين:

  1. اجعلوا الدالة tail recursion
  2. ضعوا tailrec قبل تعريف الدالة.

وإذا لم تكن دالتكم tail call ووضعتم tailrec قبلها، فإن Jetbrain IDE ذكي بما يكفي لينبّهكم إلى ذلك. :) المرجع **http://www.hpc-thai.com/?p=172

Related Articles

كيف أصمّم برمجيات؟ دليل المبتدئين لأصحاب الأعمال

كيف أصمّم برمجيات؟ دليل المبتدئين لأصحاب الأعمال

تصميم البرمجيات عملية ممتعة لكنها معقدة، تتطلب الإبداع والتفكير المنطقي ومهارات حل المشكلات.

اقرأوا المزيد
مستقبل الحوسبة الطرفية: ما تحتاج الشركات إلى معرفته

مستقبل الحوسبة الطرفية: ما تحتاج الشركات إلى معرفته

يتطور المشهد الرقمي بسرعة، وعلى الشركات أن تتكيّف لتواكب الطلب المتزايد على السرعة والكفاءة والمعالجة في الوقت الفعلي.

اقرأوا المزيد
مستقبل قطاع التجزئة: الذكاء الاصطناعي والواقع المعزّز واتجاهات التحوّل الرقمي

مستقبل قطاع التجزئة: الذكاء الاصطناعي والواقع المعزّز واتجاهات التحوّل الرقمي

يتطور قطاع التجزئة بوتيرة غير مسبوقة بفضل الذكاء الاصطناعي (AI) والواقع المعزّز (AR) وتقنيات التحوّل الرقمي. فلم تعد المتاجر التقليدية مجرد أماكن لبيع المنتجات، بل أصبحت متاجر ذكية وتفاعلية.

اقرأوا المزيد

Have a Project in Mind?

Let's discuss how we can help bring your ideas to life with our expertise in web and mobile development.

ابدأوا المحادثةhello@oozou.com
OOZOU Logo

بانكوك · سنغافورة · هونغ كونغ

X
Facebook
Instagram
LinkedIn
OOZOU Co., Ltd.
548 One City Centre
Ploenchit Road
Bangkok 10330
Thailand
+66 2544 0000
hello@oozou.com

الخدمات

  • تطوير الويب
  • وكلاء الذكاء الاصطناعي والذكاء الاصطناعي التوليدي
  • تطوير تطبيقات الجوال
  • تحليلات البيانات وهندستها
  • تصميم تجربة المستخدم وواجهته (UX/UI) وتصميم المنتجات
  • التحوّل الرقمي

الشركة

  • من نحن
  • الوظائف
  • المدونة
  • دراسات الحالة
  • عروض حية
  • تعلّمت اليوم
  • تواصل معنا

المزيد

  • القطاعات
  • شبكة الشركاء
© 2026 OOZOU. جميع الحقوق محفوظة.
سياسة الخصوصيةمدونة قواعد السلوكسياسة مكافحة الرشوة والفساد