I had a case today where I really wanted effectively a Java switch. cond seemed like overkill but then I stumbled on condp which is still more powerful than switch but pretty great for what I needed. The condp function has the following specification:
clojure.core/condp<br />
([pred expr & clauses])
where:
pred– is a predicate that takes two argumentsexpr– is an expression to apply the predicate withclauses– each clause consists of a test expression to be evaluated inpredalong withexprand the result expression. OR, there is a three-part form of the clause that does the same, but then evaluates the result expression with the result of the predicate as an argument.
Additionally, there can be a single expression at the end that is executed as an “else” if no other tests evaluate to true. The most basic example would be something like this:
user=> (defn test-condp [x] (condp = x 0 "got 0" 1 "got 1" (str "got " x))) #'user/test-condp user=> (test-condp 0) "got 0" user=> (test-condp 1) "got 1" user=> (test-condp 2) "got 2" user=> (test-condp "foo") "got foo"
Here the pred is = x and each expression will be evaluated in turn: (= 0 x) then (= 1 x) and finally the last expression if no test has evaluated to true.
The three-part form uses a special keyword :>> to set it apart and might look like this:
user=> (defn test-condp3 [k]
(condp get k
{:a 1, :b 2} :>> (partial + 3)
{:c 3, :d 4} :>> (partial + 100)
-1))
#'user/test-condp3
user=> (test-condp3 :a)
4
user=> (test-condp3 :b)
5
user=> (test-condp3 :c)
103
user=> (test-condp3 :d)
104
user=> (test-condp3 :e)
-1
Hopefully that’s clear – it was hard to come up with a great use case for this but I think this illustrates doing the lookup in the test and then passing the result onto the result expression, which avoids needing to re-access the map.
In my case, the function takes a string (read from elsewhere and passed here as value) and the sql-type (as defined in java.sql.Types) and does a conversion from the String into the appropriate value type:
(defn convert (condp = sql-type Types/SMALLINT (Integer/valueOf value) Types/DECIMAL (Double/valueOf value) Types/DATE (parse-date value **DATE-FORMAT**) Types/TIMESTAMP (parse-date value **TIMESTAMP-FORMAT**) value))
