Nas aulas anteriores, aprendemos a:

  • Preservar estado com closures
  • Evitar efeitos colaterais com imutabilidade
  • Especializar funções com currying

Agora vamos juntar tudo isso em um único conceito poderoso:

Composição de Funções.

🎯 Objetivo da aula

Ao final desta aula, você será capaz de:

  • Entender o que é composição de funções
  • Encadear funções pequenas para resolver problemas maiores
  • Escrever código mais legível e previsível
  • Reconhecer composição em código real
  • Combinar composição com currying e imutabilidade

O que é composição de funções?

Composição de funções é a ideia de:

combinar funções pequenas para formar uma função maior.

Cada função faz uma única coisa — e faz bem.

Exemplo sem composição (procedural)

Veja um código comum:

 
  function processarTexto(texto) 
  { 
    const maiusculo = texto.toUpperCase(); 
    const semEspacos = maiusculo.trim(); 
    const comPrefixo = "Resultado: " + semEspacos;
    return comPrefixo;
  }
  console.log(processarTexto(" olá mundo "));
  // Saída será: Resultado: OLÁ MUNDO

Funciona, mas:

  • Tudo está misturado
  • Dificulta reutilização
  • Dificulta testes

O mesmo problema com funções pequenas

 
  const paraMaiusculo = texto => texto.toUpperCase(); 
  const removerEspacos = texto => texto.trim(); 
  const adicionarPrefixo = texto => "Resultado: " + texto; 

Agora temos peças reutilizáveis.

Compondo funções manualmente

 
  const resultado = adicionarPrefixo( removerEspacos( paraMaiusculo(" olá mundo ") ) );
  console.log(resultado);
  // Saída será: Resultado: OLÁ MUNDO

Isso já é composição.

Criando uma função compose

Vamos automatizar essa ideia:

 
  function compose(...funcoes) 
  { 
    return function (valorInicial) 
    { 
      return funcoes.reduceRight((valor, funcao) => 
      { 
        return funcao(valor); 
      }, valorInicial); 
    }; 
  } 

Agora vamos analisar com calma a função acima, que costuma causar estranhamento à primeira vista, mas que na verdade apenas formaliza a ideia de composição de funções.

Não se preocupe em entender tudo de uma vez. Vamos desmontar essa função peça por peça.

A função inteira (vamos olhar ela “aberta”)

 function compose(...funcoes) {
return function (valorInicial) {
return funcoes.reduceRight((valor, funcao) => {
return funcao(valor);
}, valorInicial);
};
}

Antes de entrar nos detalhes, guarde esta ideia:

compose não executa nada imediatamente. Ela monta uma nova função.

1️⃣ O que é ...funcoes?

O operador ... é o rest operator.

Ele permite que a função receba um número indefinido de argumentos e os agrupe em um array.

Ou seja, ao chamar:

 compose(f1, f2, f3); 

Internamente, teremos:

 funcoes === [f1, f2, f3] 

Cada item do array é uma função que será aplicada na composição.

2️⃣ Por que compose retorna outra função?

Observe esta parte:

 return function (valorInicial) { ... } 

Isso acontece porque a composição é feita em duas etapas:

  • Primeiro, informamos quais funções serão usadas
  • Depois, informamos o valor que será processado

Exemplo:

 const processar = compose(f1, f2, f3); processar("olá"); 

Aqui temos currying e closure trabalhando juntos:

  • As funções ficam “guardadas”
  • A função retornada lembra delas

3️⃣ O papel de valorInicial

O parâmetro valorInicial representa o dado que será transformado.

Esse valor será passado por todas as funções, uma após a outra.

Mentalmente, o fluxo é este:

 valor → f3 → f2 → f1 

4️⃣ O coração da função: reduceRight

Agora vamos analisar a parte mais importante:

 funcoes.reduceRight((valor, funcao) => { return funcao(valor); }, valorInicial); 

É aqui que a composição realmente acontece.

5️⃣ O que é reduceRight?

O método reduceRight percorre um array da direita para a esquerda.

Se tivermos:

 funcoes = [f1, f2, f3] 

A ordem de execução será:

 f3 → f2 → f1 

Isso corresponde exatamente à composição matemática:

 f1(f2(f3(valor))) 

6️⃣ O acumulador (valor)

No reduceRight, o parâmetro valor é o acumulador.

Ele começa com o valorInicial e, a cada passo:

  • recebe o resultado da função anterior
  • é passado para a próxima função

O fluxo real fica assim:

 valorInicial ↓ f3(valorInicial) ↓ f2(resultado) ↓ f1(resultado) 

7️⃣ Execução passo a passo (exemplo real)


   const paraMaiusculo = x => x.toUpperCase(); 
   const removerEspacos = x => x.trim(); 
   const adicionarPrefixo = x => "Resultado: " + x;
   const processar = compose(adicionarPrefixo, removerEspacos, paraMaiusculo);
   processar(" olá ");

Internamente, a lista de funções será:

 [adicionarPrefixo, removerEspacos, paraMaiusculo] 

A execução acontece assim:

  • Primeiro: paraMaiusculo → " OLÁ "
  • Depois: removerEspacos → "OLÁ"
  • Por fim: adicionarPrefixo → "Resultado: OLÁ"

8️⃣ Por que não usar reduce?

O método reduce percorre o array da esquerda para a direita.

Isso resultaria em:

 f3(f2(f1(valor))) 

Ou seja, a ordem ficaria invertida.

Por isso, usamos reduceRight para manter a composição correta.

9️⃣ Traduzindo a função para “português”

Podemos traduzir a função compose assim:

Receba várias funções. Crie uma nova função. Quando essa nova função receber um valor, aplique as funções da última para a primeira, passando o resultado de uma para a outra.

Essa é a essência da composição de funções.

Usando compose

 
  const processarTexto = compose(adicionarPrefixo, removerEspacos, paraMaiusculo);
  console.log(processarTexto(" olá mundo "));
  // Saída será: Resultado: OLÁ MUNDO

Agora o fluxo fica:

  • claro
  • linear
  • declarativo

Composição funciona melhor com funções puras

Funções puras:

  • não alteram dados externos
  • não dependem de estado externo
  • sempre retornam o mesmo resultado
Imutabilidade + funções puras = composição previsível.

Composição + Currying

Currying cria funções de um argumento — ideais para composição.


  const paraMaiusculo = texto => texto.toUpperCase();
  function compose(...funcoes) 
  { 
    return function (valorInicial) 
    { 
      return funcoes.reduceRight((valor, funcao) => 
      { 
        return funcao(valor); 
      }, valorInicial); 
    }; 
  } 
  const adicionarSufixo = sufixo => texto => texto + sufixo;
  const comExclamacao = adicionarSufixo("!");
  const gritar = compose(comExclamacao, paraMaiusculo);
  console.log(gritar("olá"));
  // Saída será: OLÁ!

Por que isso é poderoso?

Porque agora você:

  • pensa em fluxo de dados
  • não mistura responsabilidades
  • cria código testável
  • reutiliza comportamento
Isso é base de: programação funcional pipelines de dados bibliotecas modernas

Quando não exagerar

Composição:

  • não substitui código simples
  • não deve ser usada só por estilo
Clareza vem antes de elegância.

Resumo da aula para nunca mais esquecer

  • Composição combina funções pequenas
  • Cada função faz uma única coisa
  • Imutabilidade garante previsibilidade
  • Currying facilita composição
  • Código fica mais claro e reutilizável

Na próxima etapa, entramos oficialmente no módulo avançado final, aplicando esses conceitos em arquiteturas reais e projetos mais complexos.


HARDWARE

Entendendo o seu computador

O que há dentro do meu computador?

Existem alguns componentes fundamentais presentes dentro do seu computador e é muito importante que você conheça um pouco sobre eles, seja para argumentar com algum vendedor durante a compra de um novo PC ou para identificar alguma atitude desleal de algum técnico que esteja te passando um orçamento para reparo. Na seção Raio-X aqui do Contém Bits você pode conhecer e entender mais detalhadamente sobre cada componente, ou também pode clicar abaixo no componente que deseja, para conhecê-lo melhor.

  • Gabinetes

  • Placas-Mãe

  • Processadores

  • Memória

  • Fontes

  • Drives Ópticos

  • Discos Rígidos

  • SSD

  • Placas de Som

  • Placas de Vídeo

Você Sabia?

O filme Mortal Kombat, inspirado no jogo de mesmo nome, faturou 23 milhões de dólares apenas no fim de semana de estreia nos EUA. Ainda sobre este título de sucesso, outra cifra que impressiona é o faturamento ao longo do primeiro ano: 1 bilhão de dólares no mundo todo.


Excesso de barulho dentro do seu gabinete, principalmente logo que você o liga, pode ser sintoma de problemas nas ventoinhas, que podem precisar ser limpas ou trocadas. Entre em contato com um técnico de sua confiança e verifique isso o quanto antes.


As primeiras máquinas de fliperama do mundo a utilizarem moedas, chamadas de Galaxy Game, custavam mais de 20 mil dólares para serem produzidas. Saiba mais sobre elas aqui.


O ábaco é o dispositivo de cálculo mais antigo construído e conhecido pelo homem. Suas formas mais primitivas datam de 400 a.C. e eles foram encontrados na China e na Babilônia. Para saber mais sobre a história dos computadores, clique aqui.


O título Asteroids, do Atari, possui recorde de pontuação há 30 anos. Em 1982 um americano chamado Scott Safran atingiu a marca de 41.336.440. Atualmente ele faz parte de um minúsculo grupo de jogadores que conseguiram manter seus recordes por mais de 30 anos.