Neste post, pretendo dar os conceitos básicos por tras do que é chamado programação funcional.
Pega algo para comer / beber, e leia com calma cada um dos exemplos e a explicação, pode ser um pouco maçante, mas vai valer a pena.
A programação funcional é um paradigma de programação que enfatiza a aplicação de funções. Não são todas as linguagens que suportam este paradigma.
Uma característica importante da linguagem para poder aplicar esse paradigma é que ela tenha funções de primeira classe. Nesse caso, as funções podem ser consideradas como valores, e podem ser passadas como parâmetro para outras funções.
Ficou complicado? Vamos ao código.
Abaixo, temos um código que mostra como criamos (definimos) uma função.
O function é uma palavra reservada do JavaScript, que indica que estamos iniciando a definição de uma função. O double é o nome que você está dando à função. Dentro da função, entre as chaves, está o código que a função irá executar. No caso do exemplo, ela receberá um número qualquer (number), e irá dobrar ele, ou seja, multiplicar por 2.
Em JavaScript também é possível atribuir uma função a uma variável, e essa variável passa a ser do tipo function (lembre-se que uma função pode ser um valor).
Uma vez que eu defino a função, eu consigo invocar ele a qualquer momento usando double(numero). Note que se eu não usar os parenteses na hora de invocar, eu apenas estarei passando o seu valor.
Funções como argumento
Se você ja viu codigos de JavaScript, já deve ter notado que em alguns momentos, uma função é passada para dentro outra função.
Repare que setTimeout é uma função, e ela recebe dois argumentos. O primeiro é uma função anônima (ela não tem nome, é definida apenas por function () {...}), e o segundo argumento é 1000.
Esse código faz com que depois de 1000 milisegundos, a função que você definiu no argumento seja executada. Ou seja, depois de 1 segundo, a string "Ping!" é printada no console.
Para ficar mais fácil de entender, eu poderia definir uma função qualquer, como a função que dá ping, e depois passar ela como argumento para o setTimeout.
Repare que estou passando no argumento de setTimeout apenas ping ao invés de ping(). Quando eu passo como argumento ping, eu estou passando a definição da função como argumento, para que ela seja executada dentro de setTimeout. Se eu usasse ping(), eu executaria a função no momento em que passo ela como argumento, ao invés de dentro de setTimeout.
Map
Existem funções importantes no JS que fazem uso do paradigma funcional, um deles se chama map. Mas antes de apresentá-lo, eu vou criar uma função map para mostrar de que forma posso passar funções como argumentos, e usá-los dentro da função map. Ficou confuso? Vamos aos exemplos.
A função map tem como objetivo transformar um array em outro. Ou seja, se eu quiser que um padrão seja aplicado a todos os números de um array, o map é uma excelente opção.
"Ah, mas para isso eu poderia simplesmente iterar com um for, não é?"
Sim, poderia usar um for, mas se eu quisesse triplicar os números do array por exemplo, ou aplicar qualquer outro padrão, teria que repetir o for toda vez que quisesse fazer essa modificação. Além do mais, estamos aprendendo programação funcional, certo?
Então, como eu criaria uma função myMap em que eu aplicaria um padrão para cada valor de um array, usando uma função?
A função myMap recebe como argumentos o array e uma função qualquer (func).
Dentro de myMap, eu crio um array de resultado que recebe vazio, percorro o array que recebo como argumento, e para cada elemento desse array, aplico a função que recebi via argumento - func(arr[i]), e depois jogo o resultado dessa transformação pra dentro de result - result.push(transformedNumber).
Agora aplicando a função myMap...
Nas duas vezes que eu defino a variável result, na primeira eu passo uma função que duplica um número qualquer, e na segunda eu passo uma função que triplica um número qualquer.
Dentro de myMap, essas funções que eu passei como argumento são de fato executadas e aplicadas para cada número do array.
"Aaah, mas isso pareceu muito complicado!"
Bom, de fato, como o paradigma é novo, pode parecer muito complicado, e aí temos a tendência de ficar na zona de conforto e não aprender coisas novas, mas aplicar esse paradigma é bem interessante pra inúmeras situações.
Map (nativo do JS)
O JS já tem uma função map nativa, o exemplo acima eu dei apenas como exemplo de como uma função pode ser usada como argumento.
Como na verdade o map é um método de um array, você não precisa passar o array como argumento, bastando chamar o map a partir do próprio array.
Se você for comparar, entre usar o for e o map, com map você precisou de apenas 60 caracteres e 3 linhas para transformar o array, enquanto no for, foram necessários 4 linhas e 78 caracteres.
Em um post mais para frente, veremos outras aplicações nativas de programação funcional do JS. Existem métodos prontos para filtrar, para somar elementos de arrays, e callbacks que fazem uso desse paradigma. Até mais!