# Uma Introdução ao Paradigma Funcional com Clojure > Neste artigo iremos introduzir os principais conceitos de Programação Funcional, conhecendo os seus princípios e desvendando o seu poder através de alguns exemplos práticos na linguagem [Clojure](https://clojure.org). ## Motivação Com o passar dos anos, novas necessidades foram surgindo em âmbitos específicos da computação, tais como: "o desenvolvimento da Inteligência Artificial e seus subcampos - computação simbólica, prova de teoremas, sistemas baseados em regras e processamento de linguagem natural". O paradigma predominante nas linguagens de programação da época era o imperativo - que não atendia bem a essas necessidades existentes. Desse modo, tornou-se necessário a existência de um novo modelo de programação capaz de propiciar recursos eficientes e elegantes para suprir as carências computacionais que gradativamente surgiam. Sendo assim, no início da década de 60 o paradigma funcional nasceu - originalmente na linguagem Lisp, trazendo algumas propostas substancialmente interessantes para resolver as questões que outras linguagens de programação com paradigmas distintos não conseguiam atender. ## O Paradigma Funcional: Princípios Na programação funcional a modelagem de um problema computacional é composta por uma coleção de funções que interagem entre si utilizando recursos como: composição funcional, condições e recursão. Essencialmente, "a computação é vista como uma função matemática mapeando entradas e saídas" - onde não há uma **noção de estado**, e com essa perspectiva, distingue-se diretamente dos paradigmas imperativo, lógico e/ou orientado à objeto. Nos tópicos a seguir, conheceremos os seus principais princípios. ### Imutabilidade Assim como na matemática, as linguagens funcionais possuem a característica de tratar variáveis como sendo expressões reais e imutáveis, em que não há um conceito de **célula de memória** e portanto, alteração de referência de memória. Essa característica traduz, porém, uma linguagem funcional *pura*, em que variáveis são usadas para nomear expressões imutáveis e eliminam o operador de atribuição; do contrário, são consideradas *impuras*. Observe o código a seguir: ```c= x = x + 1 ``` Neste trecho de código, em uma linguagem imperativa ou mesmo orientada a objeto, estamos realizando uma instrução de atribuição, o que significa: alterar o **estado** do programa, somando o valor `1` à variável `x` e armazenando o resultado desta soma na mesma variável que representa uma referência de memória denominada `x`. Observe abaixo um exemplo em que conseguimos realizar o mesmo comportamento do código anterior, mas desta vez sem alterar estado e célula de memória. ```clojure= (def x (+ 1)) ;; => x ;; => 1 ;; ( ) marca o início e fim de uma instrução ;; def é uma palavra chave para criarmos símbolos ;; + é uma função de adição (soma) ``` Desta forma, os nossos programas utilizam composição de funções ao invés de atualizar variáveis em memória. Como benefício, a imutabilidade nos permite conhecer mais facilmente o estágio atual da aplicação - já que cada valor referenciado no programa será sempre o mesmo de quando ele foi originalmente criado. Desse modo, lidar com questões como **concorrência** torna-se mais simples, pois uma vez que eliminamos a noção de estado, diminuímos a necessidade de gerenciar atualizações simultâneas e utilizar travas (*locks*) nos valores. ### Transparência Referencial Quando o valor de uma função depende exclusivamente do **valor de seus argumentos**, em linguagens funcionais, essa propriedade é conhecida como *transparência referencial*: ```clojure= (defn sum ([x y] (+ x y))) ;; => (sum 4 6) ;; => 10 ;; defn é uma palavra chave para definirmos uma função ;; sum é o nome da função ;; [x y] são a lista de parâmetros ``` No exemplo acima, criamos uma função chamada *sum* - que soma dois números. O valor do seu resultado depende unicamente do valor de seus argumentos e não necessita de alguma computação prévia ou mesmo da ordem de avaliação de seus argumentos. Dessa forma, as funções expressam diretamente a *pureza* que devem ter, não alterando estado e sempre retornando o mesmo valor independente do contexto. ```clojure= (defn upper-s ([msg] (clojure.string/upper-case msg))) ;; => (upper-s "Hello World!") ;; => "HELLO WORLD!" ;; upper-case é uma função que converte string em maiúsculas ``` Perceba que não importa o valor que será passado no parâmetro `msg`, o resultado retornado pela função `upper-s` será sempre o valor da string em maiúscula. ### Funções: Cidadãs de Primeira Classe Outra particularidade das linguagens funcionais, é que funções são tratadas como qualquer outro elemento da linguagem, por exemplo: strings, booleanos, inteiros, etc. Essa característica é conhecida como *first-class functions*, em que as funções podem ser atribuídas a variáveis, passadas para outras funções, retornadas por outras funções e até mesmo criadas em *runtime*: ```clojure= (def messenger (defn sender ([] (sender "Hey Jude!")) ([msg] (println msg))) ;; => (messenger) ;; => Hey Jude! ;; => (messenger "Dear Mary!") ;; => Dear Mary! ``` Neste exemplo, criamos uma função chamada `sender` e atribuímos o seu **resultado** a um símbolo que chamamos de `messenger`. Na função `sender`, declaramos duas *aridades* (número de argumentos/operandos que uma função pode ter), uma sem parâmetro e a outra com um parâmetro denominado `msg`. A primeira aridade, invoca a segunda com um valor *default* a ser impresso - resultante da invocação recursiva da função `sender`. Desse modo, é possível perceber que `messenger` pode ser invocada passando o número apropriado de argumentos (que pode ser nenhum ou um). ## Conclusão Programar no modelo funcional traz uma mudança de perspectiva que adquirimos e nos acostumamos ao longo do tempo, programando em linguagens de paradigmas diferentes. Entretanto, a medida que os princípios funcionais vão se consolidando, começamos a compreender e experimentar os benefícios que este modelo realmente proporciona. ## Referências - [Clojure Bridge](https://clojurebridge.org/community-docs) - [Clojure Reference](https://clojure.org/) - [Programming Languages: Principles and Paradigms](https://www.amazon.com.br/Programming-Languages-Principles-Maurizio-Gabbrielli/dp/1848829132)