Flow Control in Clojure

This weekend I started exploring Clojure. Getting a basic introduction around it. In this post, I will try to explore through Flow Control in Clojure

Conditionals

if

(if true "True" "False")

In Clojure, only false and nil are “false”. Even 0 is true.

(if (even? 4)
    (do (println "Even") true)
    (do (println "False") false)
)

Clojure if take only single expressions for then and else. If we have larger blocks that evaluate to single expressions, we can use do for this. This should be done when bodies have side-effects.

do according to docs in Clojure does this.

Evaluates the expressions in order and returns the value of the last. If no expressions are supplied, returns nil.

Hmmm, so this has been confusing for me. If I just println for then and else, The if expression will evaluate to nil. do gives a nice true or false as the result of the expression. So that is the purpose. I have to explore more on it.

when

when is an if with only then branch. So, if the condition is true value of the last expression is returned. On false nil is returned.

(when (even? 5) "even")

cond

cond helps with multiple conditions. A good relieve from ifelse ladder!

(let [x 10]
    (cond
        (< x 2) "x is less than 2"
        (< x 10) "x is less than 10"
    )
)

If no con Also with else accomodate an exhaustive approach

(let [x 11]
    (cond
        (< x 2) "x is less than 2"
        (< x 10) "x is less than 10"
        :else "x is greated than or equal to 10"
    ))

case

case compares an argument to a series of values to find a match in constant time! I suppose the implementation details will be interesting!

(defn foo [x]
    (case x
        5 "x is 5"
        10 "x is 10"
    )
)

case will throw an exception if it finds no value to match to. So, case support an else or default.

(defn foo [x]
    (case x
        5 "x is 5"
        10 "x is 10"
        "x isn't 5 or 10"
    )
)

Iterations

dotimes

(dotimes [i 3] 
    (println i))

doseq

(doseq [n (range 3)]
    (println n))

doseq with multiple bindings

(doseq [letter [:a :b]
        number (range 3)]
        (prn [letter number])
)

for

(for [letter [:a :b]
        number (range 3)]
    [letter number]
)