One of the first control flow statements in many programming languages is switch-case. In Clojure switch case can be achieved in different ways, which we will show in this post.

Clojure case macro

There are a couple of functions in Clojure that serve as switch case control flow statements. The first one is case macro:

(defn case-example
  " example"
  (case word
    "saluton" "Esperanto!"
    "hi" "English"

It takes an expression (here word evaluates to itself) and tries to match its result with constant in the first column and returns value from the right column when it matches. Default value can be provided as a single value, without test expression. If default value is not provided and there is no match then IllegalArgumentException is thrown.

Let’s test that:

(deftest test-case-examples
  (testing "case example"
    (is (= "Unknown" (case-example "aoeu")))
    (is (= "English" (case-example "hi")))
    (is (= "Esperanto!" (case-example "saluton")))))

Clojure cond macro

The next approach to switch case in Clojure is cond macro:

(defn cond-example
  "clojure.core.cond example"
    (< (count p) 8) "too short"
    (< 32 (count p)) "too long"
    :else "ok"))

It takes a number of pairs test expression and a value. When test expression matches the the value is returned. The last expression :else as other keywords evaluates to itself, which is boolean true, and is commonly used to denote default value. Returns nil when there’s no default.

Running the code gives:

(deftest test-cond-examples
  (testing "cond example"
    (is (= (cond-example "abc") "too short"))
    (is (= (cond-example "very long string") "too long"))
    (is (nil? (cond-example "ok one")))))

Clojure condp macro

The last one is condp:

(defn condp-example
  "clojure.core.condp example"
  [op a b]
  (condp = op
    + (+ a b)
    - (- a b)
    "Unknown operator"))

Clojure condp macro takes a binary predicate (here =) and an expression (here op) and a number of pairs test-expression,result-expression. For each clause the following expression is evaluated: (pred test-expr expr). So for arguments ‘+ 1 2 it would be (= ‘+ ‘+). When it returns true then result expression is evaluated and returned. Default value is indicated by line without separate test expression. No default value results in IllegalArgumentException when non matches.

Running the example gives:

(deftest test-condp-examples
  (testing "condp example"
    (is (= (condp-example + 1 2) 3))
    (is (= (condp-example - 1 2) -1))
    (is (= (condp-example * 1 2) "Unknown operator"))))

What next?

Now switching from Java switch-case to Clojure switch-case should be a breeze. ;-)
Check out other Clojure tutorials!

Share with the World!