Programação funcional Pt 1. — O que é programação funcional?

Caio Gomes
5 min readSep 29, 2019

--

O símbolo de programação funcional

Introdução

Programação funcional ganhou muita força recentemente com casos de sucesso e seu uso como o whatsapp que foi vendido por 19 bilhões de dólares e utiliza Erlang em sua infraestrutura suportando mais de 1 bilhão de usuários e uma equipe minúscula, ou mesmo o banco brasileiro nubank que tem o valor de mercado de mais de 10,4 bilhões de dólares utilizando Clojure e um banco de dados imutável, o Datomic. Mas o que é programação funcional, e por que usar esse paradigma?

O que é uma função?

Programação funcional vem historicamente de um conceito definido por matemáticos (afinal, computação é uma área que veio da matemática), onde os principais elementos são constantes e funções, mas… qual a diferença dos outros paradigmas se lá já existem funções?

Uma função para uma linguagem de programação é na realidade um procedimento com entradas e saídas, já em matemática uma função é uma relação entre dois conjuntos A e B, onde um elemento x de A é mapeado para um elemento y de B, onde dado x ele mapeia exclusivamente para um y, e podemos ver isso no diagrama abaixo (que você deve conhecer do ensino médio):

não é uma função

Este exemplo não é uma função pois há elementos de X que mapeiam para mais de um elemento em Y, ou seja, não podemos saber se f(3) = c ou se f(3) = d, e funções não podem ser ambiguas.

é uma função

Já neste exemplo, apesar de nem todos os elementos de y terem em um par em x, este diagrama representa uma função pois há um mapeamento único de cada elemento de x (domínio) para um elemento de y (contradomímio).

Já um procedimento é uma sequência de passos, ou seja, um procedimento pode ser utilizado como uma equivalência a uma função, mas pode realizar outras coisas, como por exemplo em um procedimento você poderia realizar diversas operações:

Exemplo de procedimento

Nesse trecho de código, 3 coisas ferem a definição de uma função, que são:

  1. O procedimento realiza instruções não relacionadas a transformação do dado
  2. O procedimento tem um retorno que não é sempre verdade, o valor de retorno da função depende do valor de x, ou seja, f(3) pode retornar qualquer valor em um dado momento se não souber o valor de x.
  3. O procedimento altera o estado de algo que não pertence ao seu escopo (uma ação denominada efeito colateral)

A ideia de programação funcional é tentar minimizar esse tipo de problema causado por um procedimento e por isso dois conceitos são extremamente importantes, que são: funções puras e imutabilidade.

Funções puras

O conceito já definido de funções matemáticas, quando transposto para computação, gera a definição de funções puras, que são funções com duas propriedades:

  1. Dada uma entrada específica a saída é sempre a mesma
  2. Ao executar uma função, não é alterado o estado da aplicação fora da função, isto é, não há efeitos colaterais

Para deixar mais ilustrativos vamos ver um exemplo de separação de um procedimento em funções puras:

Certo, esse trecho de código fere os dois princípios citados, mas isso não significa que não é possível transformar esse trecho em um trecho de código com funções puras, para isso nós vamos analisar todas as transformações que são realizadas nesse exemplo, que são:

  1. somar o valor de x com o valor de y
  2. alterar o valor de x para x + y

Então para transformar esse código devemos fazer algo que seja capaz de realizar essas duas operações agora descritas:

Agora soma_xy é uma função pura pois atende a todos os critérios definidos, embora esse seja um exemplo muito simples, o princípio é sempre o mesmo para construir funções mais e mais complexas, e como funções puras independem do estado é possível aninhar todas elas e construir funções mais complexas a partir de funções simples:

E isso pode se extender por toda e qualquer complexidade de software que seja escrito.

Imutabilidade

Um conceito que nunca paramos pra pensar quando começamos a programar é o quanto modificamos a mesma variável sem necessidade, isto é:

Esse tipo de exemplo ocorre o tempo todo nos programas, não tão claro assim, mas se você parar para olhar nos programas que você escreveu provavelmente está cheio dessas mudanças de variáveis. Isso é especialmente um problema quando se trata de paralelismo, mas vamos deixar para abordar isso em um artigo mais a frente, por enquanto vamos nos ater ao conceito de que mutabilidade é algo extremamente complicado quando se trata de analisar o estado de uma aplicação e em objetos, por exemplo:

No trecho de código acima, qual o resultado que vai ser exibido no console?

Essa pergunta não pode ser respondida porque não se sabe qual o estado da aplicação naquele momento. Nesse exemplo foi criada uma situação para mostrar uma situação limite de não saber o estado de uma aplicação, mas imagine entender o estado de uma aplicação com 20 objetos e mais de 8 mil linhas de código fazendo chamadas desse tipo? É por problemas como esse que pensamos em imutabilidade, que nada mais é que "uma vez definido um valor para uma variável aquele valor não muda", ou seja, toda vez que você queira fazer uma mudança no valor de uma variável uma cópia daquele dado deve ser gerada, isso em geral causa alguns problemas em performance mas abordaremos mais isso no futuro.

Como valores e objetos são todos imutáveis, isso nos impede de ter laços comuns como o "for", pois:

O loop for em geral vai alterar uma variável, que no caso é o "i", para poder realizar suas iterações. Mas como bons programadores e preguiçosos sabemos o quanto é importante um bom loop para poder construir os programas, para isso a programação funcional se abraça em recursões, vamos ver um exemplo dessa mudança implementando a soma de todos os números de 0 até n:

Essa implementação traz tanto uma simplicidade no desenvolvimento do software, pois fica muito mais consiso e claro o que está sendo realizado, quanto um bom exemplo das propriedades até agora discutidas.

Conclusão

Esses conceitos são extremamente úteis quando se trata de escrever programas e podem ser adotados aos poucos nos programas que escrevemos, o que pode ser extremamente útil para resolver alguns problemas que vamos entender porque as pessoas vem adotando cada vez mais esse paradigma recentemente na parte 2 dessa série sobre programação funcional.

Sobre o Autor

Meu nome é Caio Gomes, venho desenvolvendo software desde meus 12 anos de idade e sou um grande entusiasta de tecnologia e produtos, pra saber mais acesse caiogomes.dev ou me siga nas redes sociais:

Twitter / Instagram / Linkedin

--

--

Caio Gomes

sou um app developer que tenta construir os melhores produtos possíveis tanto tecnologicamente quanto na experiência de usuário