--- title: TCO Tail Call Optimization localeTitle: TCO Tail Call Optimization --- ## تحسين مكالمات الذيل (TCO) يعتبر تحسين استدعاء الذيل ( **TCO** ) حلاً لمشكلة التكدس في المكدس عند القيام بالتكرار. ### المشكلة يتم دفع كل مكالمة لوظيفة إلى رصة في ذاكرة الكمبيوتر. عند انتهاء الدالة ، يتم إفراغها من المكدس. في التكرار ، تستدعي الوظيفة نفسها بحيث تستمر في الإضافة إلى المكدس حتى تنتهي جميع تلك الوظائف. هناك ، بالطبع ، حد لهذا المكدس. عندما يكون هناك عدد كبير من الوظائف يسمى ، يتم إضافة الكثير من المكالمات إلى المكدس. عندما تكون المكدس ممتلئة ويتم استدعاء دالة ، يؤدي ذلك إلى **تجاوز سعة مكدس الذاكرة المؤقتة** نظرًا لأن المكدس ممتلئ بالفعل. لن تنتهي الدالة العودية وستؤدي إلى حدوث خطأ. #### مثال في ما يلي مثال على وظيفة مختبِس جافا سكريبت باستخدام التكرار **بدون** TCO: ` function fact(x) { if (x <= 1) { return 1; } else { return x * fact(x-1); } } console.log(fact(10)); // 3628800 console.log(fact(10000)); // RangeError: Maximum call stack size exceeded ` لاحظ أن تشغيل `fact` مع وسيطة 10000 سيؤدي إلى **تجاوز سعة مكدس** . ### استخدام TCO لحل المشكلة لحل هذه المشكلة باستخدام "تحسين مكالمات الذيل" ، يجب أن تكون العبارة التي تستدعي فيها الوظيفة نفسها في موضع ذيل. موضع الذيل هو العبارة الأخيرة التي سيتم تنفيذها في وظيفة. لذلك ، يجب أن يكون استدعاء الدالة إلى نفسها آخر شيء يسمى قبل انتهاء الدالة. في المثال السابق ، يتم تنفيذ عملية الضرب الأخيرة في عبارة `return x * fact(x-1)` ، لذلك لم تكن العملية النهائية للدالة. لذلك ، فهي ليست دعوة الذيل الأمثل. من أجل أن تكون مكالمة ذيل محسنة ، تحتاج إلى إجراء المكالمة نفسها العملية الأخيرة للوظيفة. #### مثال في ما يلي مثال على وظيفة مفاعل جافا سكريبت (ES5) باستخدام التكرار **مع** TCO. ` function fact(n) { return factTCO(n, 1); } function factTCO(x, acc) { if (x <= 1) { return acc; } else { return factTCO(x-1, x*acc); } } console.log(fact(10)); // 3628800 console.log(fact(10000)); // Infinity - Number too large, but unlike the unoptimized factorial, this does not result in stack overflow. ` لاحظ أن تشغيل `fact` على 10000 هذه المرة لن **يؤدي إلى تجاوز سعة الرصة** عند _تشغيلها في مستعرض يدعم ES6_ لأن الاستدعاء إلى `factTCO` هو آخر عملية للدالة. ### لماذا هذا يعمل عندما يلاحظ المحول البرمجي أو المفسر أن المكالمة الذاتية هي العملية الأخيرة للدالة ، فإنها تنبثق الوظيفة الحالية وتدفع المكالمة الذاتية إلى المكدس. بهذه الطريقة لا يتم تغيير حجم المكدس. لذلك ، لا تتكدس المكدس بسبب الدالة. ### ملاحظات #### معلومات اكثر: * [ما هو optmization دعوة الذيل؟](https://stackoverflow.com/questions/310974/what-is-tail-call-optimization) (ستاكوفيرفلوو) * [تحسين استدعاء الذيل في ECMAScript 6](http://2ality.com/2015/06/tail-call-optimization.html) (2ality - مدونة Dr. Axel Rauschmayer)