Ao trabalhar com desenvolvimento de software, diferentes paradigmas de programação oferecem abordagens distintas para a solução de problemas computacionais. Entre eles, destaca-se a programação funcional, uma metodologia que tem ganhado cada vez mais relevância devido à sua capacidade de produzir código mais previsível, testável e manutenível.
Neste artigo iremos explorar os fundamentos da programação funcional e suas principais características. Também veremos exemplos simples e práticos de códigos que nos ajudarão a entender melhor como esse paradigma pode ser aplicado no dia a dia dos programadores.
1 – Entendendo o conceito de programação funcional
A programação funcional (FP – Functional Programming) é um paradigma baseado no conceito de expressões e funções matemáticas. Ao aplicar a programação funcional em um projeto, os problemas serão decompostos em partes menores, as quais serão atribuídas para funções.
As funções recebem valores de entrada, aplicam uma lógica de processamento e retornam novos valores como saída. Assim, um sistema é fracionado em um conjunto de funções, cujo somatório destas funções compõem um sistema maior.
A programação funcional possui algumas características próprias. Abaixo vamos conhecer essas características e ver alguns exemplos de código escrito em JavaScript para facilitar o entendimento.
2 – As características da programação funcional
– Funções puras: são funções que retornam sempre o mesmo valor quando passados os mesmos parâmetros.
// Funções Puras+
const multiplicarPor2 = (numero) => numero * 2;
console.log(multiplicarPor2(3)); // Saída: 6
console.log(multiplicarPor2(4)); // Saída: 8
console.log(multiplicarPor2(3)); // Saída: 6
console.log(multiplicarPor2(4)); // Saída: 8
No exemplo acima, a função multiplicarPor2(), recebe um valor e multiplica-o por 2. Observe nas saídas que, sempre que uma função pura recebe o mesmo valor de entrada irá retornar o mesmo valor de saída.
– Funções de ordem superior: trata-se de uma função capaz de receber outras funções como argumento ou retornar outras funções como resultado.
// Funções de Ordem Superior
const executarOperacao = (operacao, a, b) => operacao(a, b);
const soma = (x, y) => x + y;
const multiplicacao = (x, y) => x * y;
console.log(executarOperacao(soma, 5, 3)); // Saída: 8
console.log(executarOperacao(multiplicacao, 5, 2)); // Saída: 10
No exemplo acima, executarOperacao() assume o papel de uma função de ordem superior, enquanto soma() e multiplicação(), são funções de cálculos aritméticos que podem ser passadas como argumento para a função superior executarOperacao().
– Composição de funções: é a capacidade de criar uma função a partir da junção de outras funções.
//Composição de funções
const somar = (a, b) => a + b;
const dobrar = (x) => x * 2;
const composta = () => dobrar(somar(5, 10));
console.log(composta()); // Saída: 30
No exemplo acima, temos três funções distintas: somar(), responsável por realizar um cálculo de adição entre dois valores, dobrar() que recebe um valor e multiplica-o por 2, e composta(), a qual assume o papel de uma função composta de somar() e dobrar().
– Imutabilidade: os valores após serem atribuídos para as variáveis não sofrem mudanças, mantendo-se fixos durante toda a execução do código. Ao trabalhar com dados imutáveis, novos valores são criados, ao invés de ocorrerem modificações nos valores existentes. Dessa forma, a imutabilidade torna o código mais previsível e estável, evitando efeitos colaterais inesperados no processamento.
Para um melhor entendimento desse conceito, imagine que temos um array de números e queremos adicionar um novo número a ele. Vamos visualizar dois exemplos: um utilizando uma função mutável e outro uma função imutável.
A abordagem mutável seria assim:
//Mutabilidade
const listaNumeros = [1, 2, 3];
listaNumeros.push(4); // Modifica o array original
console.log(listaNumeros); // Saída: [1, 2, 3, 4]
Observe que, em uma abordagem mutável, a constante original listaNumeros, foi modificada durante a execução através da função push().
Agora vamos observar como seria na abordagem imutável:
//Imutabilidade
const listaNumeros = [1, 2, 3];
const adicionarNumero = (lista) => [...lista, 4];
// Acrescenta um valor sem modificar o array original
const numerosAtualizados = adicionarNumero(listaNumeros);
console.log(listaNumeros); // Saída: [1, 2, 3]
console.log(numerosAtualizados); // Saída: [1, 2, 3, 4]
Observe no exemplo acima que, a função adicionarNumero() recebe um array de valores numéricos chamado listaNumeros e acrescenta o número 4. O resultado dessa operação é atribuído para a constante numerosAtualizados.
A imutabilidade dos dados pode ser observada nas saídas do código, pois, apesar da constante listaNumeros ser utilizada mais de uma vez, ela não teve seus valores alterados. Foi gerada uma nova constante chamada numerosAtualizados para gravar os dados da operação realizada com a constante listaNumeros.
– Recursividade: na programação funcional, loops de repetição não são usados. No lugar dos loops é adotada a recursividade, que é a característica de uma função chamar a si mesma até que uma condição (chamada de caso base) seja atingida.
//Recursividade
const calcularFatorial = (n) => {
if (n === 0) {
return 1;
} else {
return n * calcularFatorial(n - 1);
}};
const numero = 5;
const fatorial = calcularFatorial(numero);
console.log(`O fatorial de ${numero} é: ${fatorial}`);
//Saída: O fatorial de 5 é: 120
No exemplo acima, calcularFatorial() é uma função recursiva que calcula o fatorial do valor informado em numero.
3 – Usando paradigma funcional no dia a dia
O paradigma funcional é suportado por diversas linguagens de programação. Entre as linguagens puramente funcionais destacam-se o Haskell e a família ML (Standard ML, OCaml e suas variantes).
Nos exemplos acima, usamos JavaScript, uma linguagem multiparadigma, amplamente conhecida no mercado e compatível com os princípios da programação funcional. Mas além dela, existem outras opções disponíveis como C++, PHP, Python, TypeScript e Kotlin. Todas estas linguagens são multiparadigma e suportam a implementação de códigos seguindo o paradigma funcional.
Na prática, a programação funcional encontra grande aplicação na Ciência de Dados, especialmente no processamento e análise de grandes volumes de dados. Isto se deve à natureza concisa e declarativa do código funcional, bem como à presença de funções de ordem superior como map, filter e reduce, que simplificam significativamente o tratamento de dados.
Além disso, este paradigma mostra-se particularmente eficaz no desenvolvimento de algoritmos de busca e ordenação, assim como no processamento de eventos e sistemas reativos.
Conclusão
A programação funcional oferece uma abordagem poderosa e eficiente para o desenvolvimento de software, especialmente em aplicações que demandam alta confiabilidade e facilidade de manutenção. Ao adotar funções puras, imutabilidade, recursividade e outras características, este paradigma permite construir sistemas mais previsíveis e menos propensos a erros.
O suporte a esse estilo de programação em diversas linguagens multiparadigma, usadas por desenvolvedores no dia a dia como JavaScript, Python e Kotlin, amplia ainda mais sua aplicabilidade em diversos contextos.
Assim, a programação funcional não é apenas mais um recurso técnico, mas é um meio de transformar a maneira como abordamos problemas, tornando o código mais limpo, robusto e eficiente.
Espero que este artigo seja útil de alguma forma para você. Em caso de dúvidas, sugestões ou reclamações, fique à vontade para entrar em contato.
E se você quiser aprender mais sobre programação, acesse aqui a seção que tenho dedicada ao assunto.
Referências:
https://docs.python.org/pt-br/3/howto/functional.html
https://medium.com/trainingcenter/programa%C3%A7%C3%A3o-funcional-para-iniciantes-9e2beddb5b43
https://www.locaweb.com.br/blog/temas/codigo-aberto/programacao-funcional-e-poo-veja-as-diferencas/