freeCodeCamp/guide/portuguese/software-engineering/tco-tail-call-optimization/index.md

70 lines
3.2 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

---
title: TCO Tail Call Optimization
localeTitle: Otimização de Chamadas TCO
---
## Otimização de Chamadas (TCO)
O Tail Call Optimization ( **TCO** ) é uma solução para o problema de estouro de pilha ao fazer recursão.
### O problema
Cada chamada para uma função é enviada para uma pilha na memória do computador. Quando a função termina, ela é retirada da pilha. Em recursão, a função chama a si mesma, portanto, continua adicionando à pilha até que todas essas funções sejam concluídas. Existe, claro, um limite para esta pilha. Quando há muitas funções chamadas, muitas chamadas são adicionadas à pilha. Quando a pilha está cheia e uma função é chamada, isso resulta em um **estouro de pilha** porque a pilha já está cheia. A função recursiva não terminará e resultará em um erro.
#### Exemplo
Aqui está um exemplo de uma função fatorial JavaScript usando recursão **sem** TCO:
```javascript
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
```
Observe que executar um `fact` com um argumento de 10000 resultará em um **estouro de pilha** .
### Usando o TCO para resolver o problema
Para resolver isso usando Tail Call Optimization, a instrução onde a função chama a si mesma deve estar em uma posição final. A posição final é a última declaração a ser executada em uma função. Portanto, a chamada da função para si mesma deve ser a última coisa chamada antes que a função termine.
No exemplo anterior, a operação de multiplicação é executada por último na `return x * fact(x-1)` , portanto, não era a operação final da função. Portanto, não é otimizado. Para que seja otimizada a chamada de cauda, você precisa fazer a chamada para si mesmo a última operação da função.
#### Exemplo
Aqui está um exemplo de uma função fatorial JavaScript (ES5) usando recursão **com** TCO.
```javascript
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.
```
Observe que executar `fact` em 10000 desta vez **não resultará em um estouro de pilha** quando _executado em um navegador que suporte ES6_ porque a chamada para `factTCO` é a última operação da função.
### Por que isso funciona
Quando o compilador ou o interpretador percebe que a auto-chamada é a última operação da função, ela abre a função atual e envia a auto-chamada para a pilha. Desta forma, o tamanho da pilha não é alterado. Portanto, a pilha não transborda por causa da função.
### Notas
#### Mais Informações:
* [O que é otimização de chamada de cauda?](https://stackoverflow.com/questions/310974/what-is-tail-call-optimization) (StackOverflow)
* [Otimização de chamada de cauda no ECMAScript 6](http://2ality.com/2015/06/tail-call-optimization.html) (2ality - blog do Dr. Axel Rauschmayer)