---
# System prepended metadata

title: Uma Introdução ao Paradigma Funcional com Clojure

---

# 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 - computação simbó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)
