“If it is a good weather, I will go to a park; otherwise, I’ll go to a cafe.” This is called “if-branching” in the programming world. Since the if-branching uses simple conditionals, it is frequently used to divide into two states: true or false.

In Clojure, if is a special form. The syntax is:

(if test then else?) or (if test then)

First, the Truthiness of the test is checked. If the test turns out to be true, the then part is run; otherwise, the else? part is run (if specified). The else? part is optional.

user> (defn my-plan
        [weather]
        (if (= :good weather) "I'll go to a park." "I'll go to a cafe."))
#'user/my-plan
user> (my-plan :good)
"I'll go to a park."
user> (my-plan :bad)  ; anythigns else :good falls to else?
"I'll go to a cafe."

user> ; when else? is not given
user> (defn my-plan2
        [weather]
        (if (= :good weather) "I'll go to a park."))
#'user/my-plan2
user> (my-plan2 :good)
"I'll go to a park."
user> (my-plan2 :bad)  ; anything else :good returns nil
nil

As the if syntax shows, Clojure doesn’t have else if. If you need to be able to write else if, you can use cond, case and some more conditionals.

In addition to if, some languages have an unless conditional which runs only if the test is false. Clojure implements this with the if-not macro. The syntax is:

(if-not test then else?) or (if-not test then)

user> (defn my-plan3
        [weather]
        (if-not (= :good weather) "I'll go to a cafe." "I'll go to a park."))
#'user/my-plan3
user> (my-plan3 :bad)
"I'll go to a cafe."
user> (my-plan3 :good)
"I'll go to a park."
  • Advice to coaches

    You can show the other way to implement unless: (if (not (= ….))) This would be an example of how Clojure has many ways to do the same thing.

In addition, Clojure has a unique way of using the if conditional with the let binding. It is if-let macro, which is useful when we want to use the result of test.

The syntax is:

(if-let bindings then) or (if-let bindings then else & oldform)

user> (defn weather-is-good?
        [weather]
        (if-let [actual (= :good weather)]
                (str "The weather is good? " actual)
                "The weather is at least not good."))
#'user/weather-is-good?
user> (weather-is-good? :good)
"The weather is good? true"
user> (weather-is-good? :bad)
"The weather is at least not good."
user> ; actual is availabe only in *then* clause

user> ; if actual is referred in *else* clause
user> (defn weather-is-good?
        [weather]
        (if-let [actual (= :good weather)]
                (str "The weather is good? " actual)
                actual))
CompilerException java.lang.RuntimeException: Unable to resolve symbol: actual in this context, compiling:(/private/var/folders/4b/c9gsjvv12tq9n4mph065qs480000gn/T/form-init7461059366215401347.clj:3:9)


References