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?

Até a primeira metade dos anos 90 era bastante comum que as trilhas sonoras dos games fossem criadas por mulheres e a responsável pelas músicas do clássico Street Fighter 2 foi Yoko Shimomura. Segundo ela, o ritmo "Tararirarin" da música tema do personagem Blanka, do Brasil, veio à sua cabeça enquanto ela estava no trem a caminho da Capcom.


Utilizar seu notebook em camas, sofás ou qualquer superfície macia pode obstruir as entradas e saídas de ar, elevando a temperatura e provocando danos a diversos componentes. Utilize-o sempre sobre uma superfície rígida. Saiba mais 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.


A IBM detém o recorde de patentes em um único ano, atingindo a marca de 4186 registros no ano de 2008. Clique aqui e saiba mais sobre esta gigante do mundo da tecnologia.


Digitar senhas em computadores de uso coletivo é extremamente perigoso, pois além de softwares de monitoramento, existem dispositivos de hardware que podem capturar suas senhas. Evite ao máximo acessar sites de bancos a partir destes computadores. Veja mais aqui.