Clojure switch-case
One of the first control flow statements in many programming languages is switch-case. In Clojure switch-case can be achieved in different ways, what we will show in this article.
The case macro
There are a couple of functions/macros in Clojure that serve as switch-case control flow statements. The first one is case
macro:
1
2
3
4
5
(defn case-example [word]
(case word
"saluton" "Esperanto!"
"hi" "English"
"Unknown"))
It takes an expression (here word
evaluates to its value), tries to match its result with constant in the first column and returns value from the right column when it matches.
A 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:
1
2
3
4
5
(deftest test-case-examples
(testing "case example"
(is (= "Unknown" (case-example "aoeu")))
(is (= "English" (case-example "hi")))
(is (= "Esperanto!" (case-example "saluton")))))
The cond macro
The next approach to switch-case in Clojure is cond
macro:
1
2
3
4
5
(defn cond-example [p]
(cond
(< (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, then the value is returned. The last expression is :else
, which, as other keywords, evaluates to itself. It could be anything which evaluates itself to boolean true, however, :else
is commonly used for that purpose.
When there is no default, the case
returns nil
.
Running the code gives:
1
2
3
4
5
(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")))))
The condp macro
The last one is condp
:
1
2
3
4
5
(defn 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
from the parameters) 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 the test expression
returns true then the result expression
is evaluated and returned.
Default
value is indicated by the line without separate test expression.
When no default value is provided, condp
will throw IllegalArgumentException
if nothing matches.
Running the example gives:
1
2
3
4
5
(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 articles!