7.7 KiB
title | localeTitle |
---|---|
Clojure Conditionals | Condicionais de Clojure |
Você não vai chegar a lugar algum em um idioma, se tudo que você pode fazer é definir funções que imprimem coisas e fazem aritmética simples. Condicionais e lógicos são parte fundamental do código que faz coisas interessantes e úteis. Tente imaginar um mundo sem lógica em programas: você não seria capaz de coisas simples, como verificar se dois números são iguais!
Operadores lógicos
O Clojure, como a maioria das linguagens, possui 3 operadores lógicos: and
, or
e not
. Essas funções usam booleanos ( true
ou false
) como argumentos e retornam booleanos com base no que esses booleanos são. Como tudo em um Lisp, esses operadores usam a notação de prefixo, o que significa que eles podem parecer estranhos para você.
(and true false)
; => false
(and true true)
; => true
(or false false)
; => false
(or true false)
; => true
(not true)
; => false
(not false)
; => true
E se
if
permite executar código baseado em se um booleano é true
ou false
. if
no Clojure parece bastante estranho, não porque ele usa notação de prefixo, mas porque não há outra palavra-chave. Se a condição for verdadeira, ela avalia a primeira expressão. Se é falso, executa o segundo.
(if (= (+ 2 2) 4)
(println "Maths works!") ; this gets evaluated if 2 + 2 = 4
(println "UH OH")) ; this gets evaluated if 2 + 2 != 4
; => Maths works!
; nil
Isso apresenta um problema: e se quisermos fazer várias coisas?
(if (= (+ 2 2) 4)
(println "Maths works!")
(println "Maths still works!")
(println "UH OH"))
; => CompilerException java.lang.RuntimeException: Too many arguments to if
Felizmente, temos a do
a função de resolver este problema. do
avalia múltiplas expressões, um após o outro.
(if (= (+ 2 2) 4)
(do ; all of this gets evaluated if 2 + 2 = 4
(println "Maths works!")
(println "Maths still works!"))
(println "UH OH"))
; => Maths works!
; Maths still works!
; nil
Nota: já que if
é, em si, uma expressão, não há necessidade de um operador ternário como em muitas linguagens semelhantes a C.
var doesMathsWork = 2 + 2 === 4 ? "Maths works!" : "UH OH";
console.log(doesMathsWork);
// => Maths works!
Agora que você viu como funciona, não parece tão estranho, certo? Isso é muito mais fácil de ler e entender (ignorando a falta da palavra else
):
(def does-maths-work (if (= (+ 2 2) 4) "Maths works!" "UH OH"))
(println does-maths-work)
; => Maths works!
; nil
Alternativas para se
O Clojure também possui algumas macros que se comportam de forma semelhante a if
, e às vezes podem ser mais concisas.
if-not
é talvez o exemplo mais simples - é if
invertido. Esses dois pedaços de código são exatamente os mesmos:
(def does-maths-work (if (not (= (+ 2 2) 4)) "UH OH" "Maths works!"))
(def does-maths-work (if-not (= (+ 2 2) 4) "UH OH" "Maths works!"))
A primeira expressão é avaliada se for falsa e a segunda é avaliada se for verdadeira. Observe que o uso if-not
evita nidificação nossa condição dentro not
, o que pode ajudar a tornar o nosso código mais fácil de entender.
when
é outra macro útil. Esses dois pedaços de código também são os mesmos:
(if (= (+ 2 2) 4) (do (println "Maths works!") (println "Hooray!")))
(when (= (+ 2 2) 4) (println "Maths works!") (println "Hooray!"))
Nota: Não há when/else
. when
só executa se a condição é verdadeira.
cond
permite combinar muitas condições em uma única expressão. Ele usa uma sequência de pares de expressões e expressões lógicas e avalia cada expressão lógica em ordem. Quando encontra uma expressão lógica que avalia como true
, avalia a segunda expressão do par. Depois disso, nenhuma outra expressão é avaliada. Esse comportamento é como lógica de curto-circuito no Javascript.
(cond (= 0 1) "I'm paired with a false expression and I don't evalute.."
(= 1 1) "I'm the first expression paired with a true expression!"
(= 2 2) "I don't evalute even though I'm also paired with true ;_;"
:else "I evaluate if no other boolean expressions evaluate to true")
; => "I'm the first expression paired with a true expression!"
A palavra-chave :else
pode ser usada no lugar de uma expressão lógica no último par de expressões em cond
. Isso significa que a expressão correspondente deve ser avaliada se todas as outras expressões booleanas forem avaliadas como falsas. É o mesmo que colocar a true
como a última expressão booleana.
Formas Especiais e Avaliação
Você deve ter notado que as regras de avaliação de expressões condicionais são um pouco diferentes de outras expressões. A expressão condicional faz parte de um grupo de expressões chamado formulários especiais . Isso significa que eles não seguem as regras normais de avaliação do Clojure.
Como você sabe agora, uma expressão condicional avalia apenas a subexpressão que corresponde ao resultado booleano. Isso significa que o código inválido em uma expressão condicional não será avaliado em alguns casos. Considere as duas expressões if
abaixo. Embora (+ 1 "failure")
seja uma expressão inválida, o Clojure apenas gera uma exceção quando a condição é false
.
(if true "sucess" (+ 1 "failure"))
; => "sucess"
(if false "sucess" (+ 1 "failure"))
; => ClassCastException java.lang.String cannot be cast to java.lang.Number ...
Compare isso com o comportamento do my-if
definido abaixo:
(defn my-if [condition true-case false-case]
(if condition true-case false-case))
(my-if true "sucess" (+ 1 "failure"))
; => ClassCastException java.lang.String cannot be cast to java.lang.Number ...
my-if
é uma função com regras de avaliação normais, portanto todas as subexpressões devem ser avaliadas antes de poderem ser avaliadas.
O Clojure tem muitas macros úteis como essas para todos os tipos de tarefas. Tente dar uma olhada na documentação do Clojure e veja se você pode encontrar mais!
| Anterior | Casa | Próximo |
| Resumo | Índice | Condicionais |