Last active
June 6, 2024 03:50
-
-
Save coproduto/5550b80f96dfaebc7446eb2e7c82dc11 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* A função reduce é capaz de representar uma grande quantidade de loops imperativos. | |
| * Por que isso é possível? Reduce não é só pra extrair um valor primitivo de um array? | |
| * | |
| * Bom, não exatamente. Na verdade, o reduce *encapsula* uma lógica que representa muitos | |
| * dos loops que fazemos. | |
| * | |
| * Os argumentos do reduce são: | |
| * * Um array de algum tipo Elem de elementos; | |
| * * Um acumulador inicial de algum tipo Acc; | |
| * * Uma função que recebe um acumulador (tipo Acc), um elemento (tipo Elem) e retorna um novo acumulador; | |
| * Podemos representar essa função como Acc -> Elem -> Acc. Chamaremos esta função de agora em diante de | |
| * "função redutora". | |
| * | |
| * Quando pensamos no reduce como "resumindo" um array, vemos o acumulador como o agregado atual e a função redutora | |
| * como atualizando o agregado com um elemento do array. Então: | |
| */ | |
| const somaArray = (array) => | |
| array.reduce((somaAtual, novoElemento) => somaAtual + novoElemento, 0); | |
| // notar que em JS, o reduce é chamado como método do array, | |
| // a função redutora é o primeiro argumento e o acumulador inicial o segundo. | |
| /* No exemplo acima, a função redutora atualiza o acumulador, que começa em 0, somando cada elemento a ele. | |
| * A maioria dos casos em que usamos "reduce" para "resumir" um array tem esse formato. Mas podemos ver o reduce | |
| * de uma forma diferente. | |
| * | |
| * Podemos ver o primeiro acumulador como o *estado inicial* de um processo iterativo; | |
| * Podemos ver a função redutora como *atualizando o estado* com cada elemento novo. | |
| * Assim, podemos implementar a função que retorna os n primeiros números de Fibonacci com um loop da seguinte forma: | |
| */ | |
| const sequenciaFibonacci = (n) => { | |
| let contador = n; | |
| let anterior = 0; | |
| let atual = 1; | |
| let resultados = [] | |
| while (contador > 0) { | |
| const novo = anterior + atual; | |
| resultados.push(atual); | |
| anterior = atual; | |
| atual = novo; | |
| contador--; | |
| } | |
| return resultados; | |
| }; | |
| /* Perceba que o estado da nossa iteração tem três variáveis: "atual", "anterior" e "resultados", enquanto o | |
| * contador é utilizado para saber quantas vezes devemos repetir a iteração. | |
| * | |
| * Para fazer a mesma coisa utilizando um reduce, podemos armazenar essas três variáveis no estado da recursão: | |
| */ | |
| const sequenciaFibonacciReduce = (n) => { | |
| // por peculiaridade do JS, se queremos gerar um array de n elementos e não ligamos | |
| // pra quais os elementos sejam, precisamos fazer como abaixo: | |
| const sequencia = Array(n).fill(undefined); | |
| const estadoInicial = { | |
| anterior: 0, | |
| atual: 1, | |
| resultados: [], | |
| }; | |
| const atualizaEstado = (estadoPrevio) => ({ | |
| anterior: estadoPrevio.atual, | |
| atual: estadoPrevio.anterior + estadoPrevio.atual, | |
| resultados: estadoPrevio.resultados.concat(estadoPrevio.atual), | |
| }); | |
| return sequencia.reduce(atualizaEstado, estadoInicial).resultados; | |
| } | |
| /* Então percebam: Convertemos o estado da iteração em uma estrutura de dados e a iteração em si | |
| * em uma função atualizadora do estado, e geramos uma sequência que garante que a iteração seja executada | |
| * o número correto de vezes. | |
| * | |
| * Em quase todo loop imperativo, pensamos em um estado sendo atualizado em um número de iterações dado ou | |
| * por um número ou por uma estrutura de dados. | |
| * | |
| * A função reduce encapsula essa lógica de ter um estado que é atualizado um determinado número de vezes, | |
| * recebendo explicitamente um estado inicial e um "atualizador". | |
| */ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment