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 inpred
along withexpr
and 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))