Funções em Clojure

guilhermelo

Guilherme Rodrigues de Melo

Posted on January 8, 2021

Funções em Clojure

Vimos no post anterior como são as estruturas básicas de dados em Clojure. Nesse post, veremos como declarar e trabalhar com funções na linguagem Clojure.

Definindo funções

A criação de uma função é dividida em cinco partes, sendo elas:

  1. defn
  2. Nome da função
  3. A documentação da função, sendo opcional
  4. Parâmetros que são passados entre colchetes
  5. Corpo da função

Criando nossa primeira função em Clojure:

(defn ola
"Função que retorna um texto de boas vindas!"
[nome]
(println "Olá, " nome))
Enter fullscreen mode Exit fullscreen mode

Acima definimos o nome da nossa função como "ola", escrevemos uma documentação simples, passamos "nome" como parâmetro e criamos um corpo da função que imprime a frase retornada.

Invocando a função:

(ola "Guilherme")
; Olá Guilherme
Enter fullscreen mode Exit fullscreen mode

Parâmetros e Aridade

Em linguagens orientadas a objetos podemos ter métodos com o mesmo nome, porém com quantidade de parâmetros diferentes na mesma classe. Em Clojure, temos algo parecido. Podemos definir que uma função pode ter diferentes formas de implementação com diferentes aridades (número de parâmetros passados para a função), o que chamamos de sobrecarga de aridade (arity overloading). Abaixo nossa função "ola" ganha novas aridades e para isso, devemos modificar um pouco a forma como escrevemos a função, envolvendo cada forma de implementar com parênteses.

(defn ola
"Função que retorna um texto de boas vindas!"
([nome]
(println "Olá," nome))

([nome sobrenome]
(println "Olá," nome sobrenome))

([nome sobrenome idade]
(println "Olá," nome sobrenome ". Idade:" idade "anos")))
Enter fullscreen mode Exit fullscreen mode

Invocando a função utilizando as três formas:

(ola "Guilherme")
; Olá, Guilherme

(ola "Guilherme" "Rodrigues")
; Olá, Guilherme Rodrigues

(ola "Guilherme" "Rodrigues" 23)
; Olá, Guilherme Rodrigues . Idade: 23 anos
Enter fullscreen mode Exit fullscreen mode

Clojure também nos permite definir uma função com aridade variável através do parâmetro rest (rest parameter). Para indicar que estamos utilizando rest parameter, devemos utilizar o simbolo & como no exemplo abaixo.

(defn imprime-nome [nome]
    (println "Olá" nome))

(defn ola [& nomes]
    (map imprime-nome nomes))
Enter fullscreen mode Exit fullscreen mode

No exemplo acima definimos uma função chamada imprime-nome passando como parâmetro o nome. Utilizamos a função imprime-nome para mapear a lista de argumentos e imprimi-los. Invocando a função com os parâmetros:

(ola "Guilherme" "João" "José")

; Olá Guilherme
; Olá João
; Olá José
Enter fullscreen mode Exit fullscreen mode

Para utilizar rest parameter juntamente com outro parâmetro, devemos passa-los como último parâmetro da função. Exemplo:

(defn mostra-time [time & nomes]
    (println "Os jogadores do" time "são: " 
        (clojure.string/join ", " nomes)))
Invocando a função:

(mostra-time "Real Madrid" "Benzema" "Casemiro" "Rodrigo")
; Os jogadores do Real Madrid são: Benzema, Casemiro, Rodrigo
Enter fullscreen mode Exit fullscreen mode

Desestruturação

Clojure nos permite extrair valores dos parâmetros que são passados para a função utilizando um conceito chamado destructuring. No exemplo abaixo recuperamos apenas o primeiro elemento da coleção passada como parâmetro e retornamos o mesmo.

(defn primeiro-elemento [[primeiro-elemento]]
    primeiro-elemento)

(primeiro-elemento ["Carro" "Bicicleta" "Caminhão"])
; "Carro"
Enter fullscreen mode Exit fullscreen mode

Clojure nos permite utilizar a desestruturação com rest parameters como no exemplo abaixo:

(defn dois-primeiros-elementos-e-resto [[primeiro segundo & resto]]
    (println "Primeiro:" primeiro)
    (println "Segundo:" segundo)
    (println "Outros:")
    (println (clojure.string/join ", " resto)))

(dois-primeiros-elementos-e-resto ["Carro" "Bicicleta" "Caminhão" "Metrô" "Ônibus"])

; Primeiro: Carro
; Segundo: Bicicleta
; Outros:
; Caminhão, Metrô, Ônibus
Enter fullscreen mode Exit fullscreen mode

Também é possível utilizar desestruturação com mapas. No exemplo abaixo os valores das chaves :nome e :sobrenome informadas são passados para os parâmetros nome e sobrenome:

(defn ola [{nome :nome sobrenome :sobrenome}]
(println "Nome:" nome)
(println "Sobrenome:" sobrenome))

(ola {:nome "Guilherme" :sobrenome "Rodrigues"})

; Nome: Guilherme
; Sobrenome: Rodrigues
Enter fullscreen mode Exit fullscreen mode

Corpo de função

O corpo da função pode conter inúmeras formas dentro dele. Porém, Clojure retorna apenas a última expressão avaliada pela função. No exemplo abaixo temos diversas formas, porém apenas a última é retornada:

(defn corpo-funcao []
    (+ 10 15)
    "Corpo da função"
    (* 100 12))

(corpo-funcao)
; 1200
Enter fullscreen mode Exit fullscreen mode

Funções anônimas

Acima fizemos um exemplo utilizando a função map e passamos a função imprime-nome como parâmetro. Relembrando a função:

(defn imprime-nome [nome]
    (println "Olá" nome))

(defn ola [& nomes]
    (map imprime-nome nomes))
Enter fullscreen mode Exit fullscreen mode

Porém, em Clojure não é necessário que todas as funções tenham nomes, pois a linguagem nos possibilita utilizar funções anônimas. Vejamos abaixo como podemos utilizar funções anônimas nesse caso:

(defn ola [& nomes]
    (map (fn [nome] 
           (println "Olá" nome)) nomes))

(ola "Guilherme" "João")         

; Olá Guilherme
; Olá João
Enter fullscreen mode Exit fullscreen mode

Como visto, para definir uma função anônima, trocamos o defn por fn, retiramos o nome da função e passamos como parâmetro de outra função. Porém, podemos diminuir mais um pouco a definição da função anônima. Para isso, deixamos de utilizar o fn, não definimos o nome do parâmetro e substituimos o parâmetro apenas por %. Exemplo acima com função encurtada:

(defn ola [& nomes]
    (map #(println "Olá" %) nomes))

(ola "Guilherme" "João")    

; Olá Guilherme
; Olá João
Enter fullscreen mode Exit fullscreen mode

Caso a função anônima receba mais de um parâmetro, é possível utiliza-los como no exemplo abaixo:

(#(+ %1 %2) 10 15)
;25
Enter fullscreen mode Exit fullscreen mode

Espero que tenha gostado das funções em Clojure. Por enquanto é só e nos vemos em um futuro post. Abraços :)

💖 💪 🙅 🚩
guilhermelo
Guilherme Rodrigues de Melo

Posted on January 8, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related