Fundamentos básicos da Programação Funcional

Talvez pareça contraintuitivo para você que a imagem inicial de um artigo sobre programação seja um quadro contendo funções matemáticas. Mas, na verdade, programação funcional tem tudo a ver com matemática e suas raízes estão no cálculo lambda (cálculo-λ), que foi um sistema desenvolvido em 1930 para expressar computação usando funções e cujas características foram utilizadas como base para criação da LISP, primeira linguagem de programação dita funcional, ainda em 1950. A seguir, vamos entender quais são estas características dentro do contexto da linguagem Swift.

O paradigma funcional

Programação funcional não é uma linguagem, não é uma sintaxe, mas sim uma maneira de se pensar sobre problemas e sua resolução. É um paradigma diferente.

Um paradigma de programação fornece e determina a visão que o programador possui sobre a estruturação e execução do programa. Por exemplo, em programação orientada a objetos, pode-se abstrair um programa como uma coleção de objetos (instâncias que representam uma abstração de entidades) que interagem entre si, enquanto em programação imperativa os programadores abstraem o programa como uma sequência de ações executadas de modo sequencial.

Por sua vez, o paradigma funcional é caracterizado basicamente pela ausência de efeitos colaterais em sua execução. É um paradigma que trata a computação como uma avaliação de funções matemáticas, e que evita estados ou dados mutáveis. Ela enfatiza a aplicação de funções para resolver um dado problema, em contraste da programação imperativa, que enfatiza alterações no estado. Para ficar mais claro, vamos a um exemplo do que é um código funcional comparado a um imperativo:

Imperativo

Funcional

Percebe a diferença? No código não funcional acima, a função increment() está modificando além de seu escopo interno, alterando o valor de dados (variável a) fora dela. No contexto de programação funcional isto não deve ocorrer, como vimos na definição.

Além disso, o paradigma funcional é declarativo, o que significa que a programação é feita com expressões ou declarações ao invés de statements (unidades sintáticas de uma linguagem de programação imperativa que expressam alguma ação a ser executada).

Os pilares da programação funcional

Programar funcionalmente não é apenas o que foi mostrado acima, vamos agora aprender conceitos importantes que fazem parte deste paradigma.

Pure Functions

O primeiro conceito fortemente relacionado ao paradigma funcional é o de funções puras.

Para uma função f ser considerada pura, o resultado da mesma depende apenas dos argumentos que são passados ​​para ela, ou seja, ao chamar f duas vezes com o mesmo valor para um argumento x produz o mesmo resultado f(x) em ambas as execuções, isso está em contraste com procedimentos que dependem de um estado local ou global, podendo produzir resultados diferentes em momentos diferentes. Portanto, uma função pura não modifica valores fora de seu escopo, não produz efeitos colaterais e pode ser facilmente reutilizada ou composta com outras funções para a resolução de um dado problema.

Dada esta definição, revisite os códigos de exemplo acima e perceba que a primeira função increment() se trata de uma função impura enquanto a segunda implementação está dentro da definição e, portanto, é uma função pura.

É importante ressaltar algo que no exemplo simples não foi notório. Imagine que você está criando uma função complexa, que em seu escopo utiliza vários métodos. Neste tipo de situação é necessária atenção ao que inserir no corpo de sua função para que ela seja, de fato, pura.

Higher Order Functions

Em linguagens que suportam programação funcional, como é o caso de Swift, funções são valores. E funções de alta ordem são simplesmente funções que operam em outras funções, ou seja, podem receber uma função como entrada ou retornar uma função como saída.

A biblioteca padrão de Swift conta com diversas funções de alta ordem, como por exemplo filter, map e reduce. Apenas para entender o comportamento, vamos a um exemplo utilizando a função filter, que itera sobre uma coleção e retorna uma coleção filtrada de acordo com o critério desejado.

Imagine que você possui o seguinte código não-funcional:

O exemplo é bem simples, queremos um array a partir do original que contenha apenas os elementos ímpares. Vamos ver como isto é feito funcionalmente com o filter.

A condição para realizar o filtro dos elementos ímpares é inserida na closure entre chaves ({}) e de maneira sucinta a função realiza a tarefa. Esta é a beleza das funções de alta ordem, toda a lógica que inserimos foi a da linha:

return number % 2 != 0

E o filter é responsável por toda a iteração na coleção original e inserção na nova coleção, tudo que precisamos é passar a condição desejada.

Podemos ainda tornar nosso código mais elegante e reutilizável.

Viu só? Desacoplamos nossa condição tornando-a independente. Se em qualquer outro lugar do código quisermos utilizá-la, is_odd estará lá disponível.

Recursion

Recursão também é um conceito muito importante envolvido com programação funcional. Uma função é dita recursiva quando ela chama a si mesma, agindo como um loop, ou seja, executando o mesmo código várias vezes dado um critério de parada que é chamado de caso base. Exemplo:

Utilizar a recursão como alternativa aos loops se mostra relevante em um contexto funcional pois loops requerem um estado mutável em sua execução. Isso significa que deve haver uma variável mutável, que é proibida em um ambiente puramente funcional. Aqui vale ressaltar que, não é o caso de Swift, mas linguagens puramente funcionais, como Haskell, são projetadas para operar sem a necessidade de iteração, respeitando a natureza do paradigma funcional.

Diferenciais do paradigma funcional

Agora que cobrimos as principais nuances que, juntas, caracterizam a programação funcional, algumas vantagens merecem ser destacadas antes do final desse artigo.

Código funcional é extremamente modular

Como funções são as bases do paradigma funcional, imagine ter várias funções curtas e que, juntas, irão se compor pra resolver o seu problema, podendo ser reutilizadas sempre que necessário.

Código funcional é imutável e seguro

Já conversamos bastante sobre funções puras serem livres de modificações fora de escopo, este é um dos motivos que torna a programação funcional bastante segura para o programador.

Além disso, este paradigma não encoraja a criação de variáveis, mas de constantes, o que dá maior controle ao programador sobre o que de fato está acontecendo. Imagine uma situação: ao escrever código para um sistema multi-thread, se duas ou mais threads acessarem a mesma variável simultaneamente, elas poderão modificá-la ou acessá-la fora de ordem, causando inconsistências. Se você pudesse escrever código onde o estado nunca sofreu uma mutação, esses problemas desapareceriam. Sistemas que funcionam assim têm estado imutável, o que significa que o estado não pode mudar durante o curso de um programa.

Código funcional é fácil de testar

A partir de tudo que foi dito anteriormente, um código puro é também fácil de testar. Funções com ausência de efeitos colaterais criam para o programador um cenário no qual não existe mais a necessidade de fazer mocks em todo o código para testá-lo.

Código funcional é legível

Imagine que seu programa possui milhares de linhas de códigos, funções e variáveis, ter visão sobre tudo que está acontecendo se torna bastante dispendioso. O programador de funcional irá lidar com código mais curto e simples, com funções bem definidas e sem mudanças de estado. Ou seja, código legível.

Próximos passos

Conteúdos interessantes que podem ajudá-lo a dar continuidade ao estudo de programação funcional:

Obrigada por ter chegado até aqui e bons estudos! :)

--

--

--

software developer @ guava.software

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Paula Vaz

Paula Vaz

software developer @ guava.software

More from Medium

Integrating Auth Service into Your Xamarin.Android App That Requires Twitter Account Sign-in

Calendar ListView in HarmonyOS

Unexpected end of JSON input error occurred when executing yarn install

What is new in Flutter 3?