---
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)