DEV Community

Cover image for Criando variáveis e funções em Clojure
Arthur Fücher
Arthur Fücher

Posted on

Criando variáveis e funções em Clojure

O básico para começar a desenvolver em uma linguagem (funcional) é aprender a criar variáveis para armazenar os dados e funções para poder trabalhar com esses dados.

Vamos ver na prática como trabalhar com variáveis e criar funções, para isso vamos usar o REPL. Se ainda não sabe o que é, conheça REPL - seu melhor amigo no mundo clojure

Criando variáveis

Clojure preza pela imutabilidade, então quando criamos uma variável estamos definindo um símbolo com um valor.

user=> (def foo 1)
#'user/foo
Enter fullscreen mode Exit fullscreen mode

Nesse exemplo estamos definindo foo com o valor 1, o retorno é o nome completo do símbolo criado #'user/foo. Quando criamos, o Clojure cria na namespace atual, que no caso é user. Quando temos um arquivo, ele vai ter a própria namespace, e tudo criado lá dentro será pertencente aquela namespace.
Agora podemos acessar o valor direto ou usá-lo passando para uma função:

user=> foo
1
user=> (inc foo)
2
user=> foo
1
Enter fullscreen mode Exit fullscreen mode

Notamos nesse exemplo que o valor de foo não mudou após a execução de inc. Isso é evidência a característica de imutabilidade que comentamos, ou seja, o valor não é alterado e sim o novo valor é retornado.
Você pode estar pensando:

"podemos chamar o def novamente com o mesmo nome?"

Sim, isso iria "redefinir". Mas não é recomendado fazer isso, então nem pense nisso 😅

Criando funções

Da mesma maneira que usamos def para atribuir um valor simples, fazemos para criar uma função. Vamos criar uma função chamada ola que recebe um parâmetro nome e imprime Olá <<nome>>:

(def ola
  (fn [nome]
    (println (str "Olá " nome))))
Enter fullscreen mode Exit fullscreen mode

Estamos atribuindo a ola uma função, que definimos usando fn. Usamos [] para declarar os parâmetros que recebemos, e depois o corpo da função.
Agora podemos executar a função igual as outras que já vimos:

user=> (ola "mundo")
Olá mundo
nil
Enter fullscreen mode Exit fullscreen mode

Retornando valores

No exemplo anterior, vimos que depois de imprimir a mensagem aparece nil, isso representa o retorno da nossa função. Em Clojure as funções retornam a última operação/valor.

user=> (defn soma2 [x] (+ x 2))
#'user/soma2
user=> (soma2 1)
3
Enter fullscreen mode Exit fullscreen mode

(def + fn)

Clojure criou uma maneira um pouco mais simplificada para a criação funções.
Ao invés de escrever def foo (fn []...) para atribuir uma função, podemos utilizar defn. O exemplo anterior ficaria assim:

(defn ola
  [nome]
  (println (str "Olá " nome)))
Enter fullscreen mode Exit fullscreen mode

Aridade

A aridade de uma função é a quantidade de parâmetros que ela recebe. Em Clojure podemos definir na mesma função múltiplas aridades, isso pode ser usado por exemplo para definir parâmetros opcionais ou valores default.
Vamos alterar a função ola para que quando for chamada sem nenhum parâmetro imprima "Ola mundão":

(defn ola
  ([] (ola "mundão"))
  ([nome] (println (str "Olá " nome))))
Enter fullscreen mode Exit fullscreen mode

Cada aridade é declarada envolta em () e declaramos da menor aridade para a maior.
Vamos executar novamente a função, não passando parâmetro e passando:

user=> (ola)
Olá mundão
nil
user=> (ola "mundo")
Olá mundo
nil
user=> (ola "mundo" "grande")
Execution error (ArityException) at user/eval2032 (REPL:1).
Wrong number of args (2) passed to: user/ola
Enter fullscreen mode Exit fullscreen mode

Note que quando chamamos a função passando um número de argumentos que não existe, recebemos uma ArityException.

Funções: de primeira classe

Em Clojure as funções são armazenadas e tratadas como os outros valores, portanto podem ser passadas como argumentos para outras funções 🤯
Para exemplificar, vamos criar uma função que receba o nome da pessoa e a forma como queremos cumprimentar:

(defn cumprimentar
  [nome cumprimento] 
  (cumprimento nome))
Enter fullscreen mode Exit fullscreen mode

E podemos executá-la:

user=> (cumprimentar "Ariel" ola)
Olá Ariel
nil
Enter fullscreen mode Exit fullscreen mode

Veja que a função cumprimentar recebe o cumprimento e executa passando o nome, que também veio como parâmetro, para ela.

Docstring

Outra coisa importante é que quando declaramos uma função podemos criar junto uma documentação/descrição do que ela faz. Para isso basta passar antes dos parâmetros uma string com a descrição:

(defn ola
  "Recebe um nome e devolve Olá <<nome>>"
  [nome]
  (println (str "Olá " nome)))
Enter fullscreen mode Exit fullscreen mode

E agora, podemos usar a função doc que vimos no outro post passando a nossa função:

user=> (doc ola)
-------------------------
user/ola
([nome])
  Recebe um nome e devolve Olá <<nome>>
Enter fullscreen mode Exit fullscreen mode

Muito legal né? 🤩

Valores locais

Em Clojure podemos atribuir valores locais a nomes, dentro do escopo de funções, usando o let. Esses valores serão constantes, ou seja, não poderemos mais alterar ou redefinir.
Com o let você pode criar de uma vez 1 ou mais constantes, ele segue a seguinte estrutura:

(let [nome valor
      nome valor]
  ;;Podemos utilizar dentro do escopo do let
)
Enter fullscreen mode Exit fullscreen mode

Para exemplificar vamos alterar a função anterior para criar a string e armazenar localmente, e depois imprimir.

(defn ola
  [nome]
  (let [mensagem (str "Ola " nome)]
    (println mensagem))) 
Enter fullscreen mode Exit fullscreen mode

Criamos a mensagem com a string completa dentro do let e depois chamamos o println.


Espero que tenha gostado do conteúdo! Se sim, compartilhe, comente e/ou deixe uma reação. Isso ajuda a trazer visibilidade e saber que estão curtindo!
E se não gostou, comenta aí o que poderia melhorar! Quem sabe o próximo post você goste?

Abraços e até breve

Top comments (0)