Este post é uma continuação do post sobre conceitos de programação funcional. Para ver a primeira parte, veja aqui.

Filter

Na primeira parte sobre conceitos de programação funcional, vimos como conseguimos passar funções como argumentos, para serem executados dentro de outras funções. Vimos também um exemplo com a implementação customizada da função map, e também como funciona o map nativo do JS.

Agora, vamos ver como funciona o filter. O filter é uma função / método em que o resultado trazido é um array que pode ser menor do que o array original, já que passamos para ele uma função com uma condição que deve ser usada para filtrar o array original.

Repare que no exemplo acima foi passado uma função anônima que recebe um argumento number, e retorna uma condição (se resto de número dividido por 2 é igual a 0, ou seja, se é par).

Nesse caso, a função que um filter geralmente recebe na maioria das vezes costuma a ser uma condição que deve ser checada para filtrar o array original.

Novamente, se formos comparar com uma versão for, o filter é bem mais simples de se escrever. Com o for, usaríamos 106 caracteres, com cerca de 6 linhas, e usando apenas um filter, conseguimos enxugar o código para apenas 69 caracteres e 3 linhas.

Reduce

O reduce é outra função que faz uso do paradigma funcional no JS, e pode ser usada para muitas aplicações.

O reduce permite que você trabalhe com um array de forma a retornar um resultado apenas, que pode ser a soma de todos os elementos, pode ser também algum tipo de rearranjo dos valores do array... Enfim, fica a cargo da sua criatividade.

Vamos aos exemplos? Um exemplo simples para começar seria retornar o somatório de um array.

Hum, parece um pouco complicado, não?

O primeiro argumento que deve ser passado na função argumento para o reduce é o acumulador. No exemplo, ele é o acc. Essa variável é a que irá, dentro do reduce, acumulando os valores de qualquer operação que você fizer dentro da função que você passou como argumento.

O segundo argumento que deve ser passado na função argumento é o valor corrente. No caso do exemplo, é o value. Lembrando que você pode usar quaisquer nomes, já que o conceito não muda.

O 0 passado como segundo argumento do reduce (cuidado, aqui o 0 não é um argumento da função anônima, mas sim do reduce) é o valor inicial que o acumulador deve ter. Ele é opcional.

Mas o que acontece exatamente dentro do reduce? Por dentro do reduce, o acumulador recebe o resultado da interação que a função que você passou como argumento faz. Podemos verificar isso dando um print para cada iteração que o reduce faz.

O primeiro valor do acumulador é 0, que foi o valor passado como argumento de valor inicial do acumulador. O valor corrente no primeiro loop é 1 (primeiro valor do array).

No segundo loop, o acumulador recebeu o primeiro valor corrente, e passa a valer 1 (o valor corrente passa a ser 2, o segundo valor do array).

No terceiro loop, o acumulador vale 3, que é resultado do valor do acumulador + 2.

No quarto loop, o acumulador vale 6, e assim por diante... Repare que o acumulador se comporta exatamente como seria no caso de uma iteração que você faria para somar elementos de um array.

Mais que apenas somatório de números...

Bom, mas o reduce pode ser usado para inúmeros objetivos, e não apenas para somatórios de números. Vou mostrar um exemplo.

Digamos que você receba uma matriz de chaves e valores, e você queira transformar ele em um objeto. O reduce é uma ótima opção. Como?

Na função anônima que passo pro reduce, eu separo quem vai ser a chave e quem vai ser o valor (key recebe current[0], e value recebe current[1]).

Em seguida, eu crio uma chave no objeto acc, recebendo o valor estabelecido para a chave (repare que eu inicio o acumulador como um objeto vazio {}).

Por fim, eu devo retornar o próprio acumulador, para que ele vá sendo atualizado em cada loop. No final de tudo eu tenho um objeto formado com as chaves e valores correspondentes.

O reduce é mais complexo que o map ou o filter, mas as possibilidades que ele oferece são infinitas, e creio que eu mesmo não aproveitei tudo que ele tem a oferecer ainda, mas é bacana tentar se desafiar a usar essas ferramentas nos seus projetos. Uma vez que você pegue o gosto, vai virar um addict também, hahaha. :P

No próximo post, pretendo falar sobre como você pode se aproveitar de funções para criar callbacks em funções próprias. Até mais!