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
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
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))))
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
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
(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)))
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))))
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
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))
E podemos executá-la:
user=> (cumprimentar "Ariel" ola)
Olá Ariel
nil
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)))
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>>
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
)
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)))
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)