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

3.2 KiB
Raw Blame History

title localeTitle
TCO Tail Call Optimization 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:

  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.

  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: