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)