Função de Ordem Superior com Reduce — Compose do Recompose
Introdução
Olá, tudo bem? Quero falar de um assunto bem avançado de Javascript.
Motivação
Que Javascript é difícil quando você começa avançar nos estudos nós já sabemos, se você entender o que vou explicar nesse post, interiorizar, saber aplicar, o seu JS é avançado! Pode ter certeza! Me falaram isso, então posso repassar essa afirmação.
Nesse post vamos entender esse algoritmo:
Pré-requisito
para continuar lendo:
- Saber o básico de Javascript (const/let/var).
- Conhecer ES06, desestruturação de parâmetros, arrays, funções, arrows functions, HOF, e "só".
- Ser curioso, vontade de aprender, perguntar e dar feedback.
Caso de Uso
A função compose é muito útil em aplicações React que usam a lib Recompose para lidar com Smart/Dumb componentes e escrever menos linhas de código. No exemplo abaixo, no final da linha executo o compose que retorna para o BirthdaysContainer o componente puro Birthdays que é apenas a tela de aniversariantes com os dados carregados, data e withApollo. O BirthdaysContainer é usado no Router, e Router renderizado no App.js e assim vai subindo a árvore de componentes do React… Vamos voltar para o assunto, só quis colocar aqui uma vantagem de usar o recompose/compose.
Explicação
Leia o código mais uma vez, é meio chato debugar reduce, então vou deixar aqui "mastigado" o que está acontecendo trecho por trecho, qualquer dúvida, sugestão ou correção pode comentar.
Para me ajudar a exemplificar vou criar cinco funções de soma bem simples, que recebem um número como parâmetro e realiza a soma com o valor especificado na função:
A função add1 recebe um número e soma por 1, função add2 recebe um número qualquer e soma por 2 e assim sucessivamente para função add3, add4 e add5.
Compose
Veja na linha 10 o console.log() que serve apenas para exibir o resultado da chamada da função compose.
Quando o compose é chamado, estou passando para o compose as cinco funções como argumento/parâmetro e como o retorno do compose é uma função então eu passo outro parâmetro (5) para o retorno da função.
Veja o código abaixo, se você chamar só o compose passando uma função, então ele retorna função.
Se você chamar a função e passar um parametro para a função que foi retornada então ele executa a função retornada com o parâmetro informado, no exemplo acima informei 5 e recebi a soma de 5 +1 = 6.
Os argumentos que forem recebidos no compose serão desestruturados e será criado um array com todos os parâmetros.
Logo, se eu fizer a chamada como no exemplo abaixo vou ter esse resultado (linha 7):
É por isso que posso usar o reduce, na variável funcs, pois funcs é um array dos parâmetros recebidos.
Esse reduce retorna um HOF.
(…args) => a(b(…args)
Parametro a é o acumulador e o parâmetro b é o valor atual do array.
Consequentemente o acumulador do A na primeira iteração será primeiro valor do array [add1] e o valor de B será a segunda posição do array [add2], pois não foi passado nenhum valor inicial, e o args são os argumentos que a função pode receber.
Reduce reference, consulte a documentação de reduce se tiver alguma dúvida, eu sempre faço isso!
// Reduce / Reduzir
a = acumulador
b = valor atual do array
Como cada elemento do array é uma função ficaria assim a cada interação:
A função foi só resolvendo, não foi chamando, a chamada é depois que termina a iteração e o reduce retorna a função e executa.
Após o final da quinta iteração acima, o reducer retorna o resultado da execução da função, ele vem reduzindo (resolvendo):
Vemos claramente o retorno e chamada da função, função que chama função, função que retorna outra função, ou Função de Ordem Superior (HOF).
Logo o resultado dessa chamada, é o valor 20.
5 + 5 = 10 + 4 = 14 +3 = 17 + 2 = 19 + 1 = 20
Pronto, é isso ai! Tudo isso pra isso! rsrs.
A maior complexidade é entender o fluxo do reduce dentro de um array de funções, e o pior que ele retorna uma função, isso é meio mágico e díficil de debugar.
Agora tudo fica mais claro na hora de usar algumas libs famosas e até mesmo desenhar seus próprios sistemas. Essa função usa fortemente o conceito de programação funcional, dá para perceber que ela é bem declarativa, ela vai fazendo sem você dar muitas instruções (imperativo) de como fazer.
É bem complicado e demora para entender no começo mas depois você vai interiorizando, escrevi justamente para eu pegar bem esse conceito e repassar o que tenho aprendido e obter um feedback.
Obrigado por ler, se gostou deixa umas palmas ai!