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:
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:
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
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
Quando não exagerar
Composição:
- não substitui código simples
- não deve ser usada só por estilo
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.
Você Sabia?
Inteligência artificial
O primeiro jogo a fazer uso de uma Inteligência Artificial foi o Mouse in the Maze, criado em 1955, na União Soviética. Você pode saber mais sobre ele clicando aqui.
Ábaco
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.
Ultima Online
Criar um jogo é muito mais complexo do que parece. São milhares, às vezes, milhões de linhas de código. Isso não é exagero! Apenas o jogo Ultima Online possui 6.006.313 linhas de programação, totalizando 25.103.295 palavras
Pac Man
Apenas no ano de 1982, o clássico Pac Man vendeu mais de 400 mil máquinas de fliperama em todo o mundo e recebeu cerca de 7 bilhões de moedas nestas máquinas. Saiba mais.
Civilization
A empresa Take-Two pagou à Infogrames mais de 22 milhões de dólares pelos direitos de Civilization, em novembro de 1994. Ainda sobre este título, Sid Meier, um dos seus fundadores, é o profissional da área dos games mais premiado em todo o mundo.










