Clojure: how to switch to Java classes
I have a java class in clojure that comes from a method that returns classes. I want the case to switch to them, for example:
(case type
java.lang.String (println "Found String" name)
java.lang.Long (println "Found Long" name)
java.nio.ByteBuffer (println "Found ByteBuffer" name)
java.lang.Boolean (println "Found Boolean" name)
java.math.BigDecimal (println "Found BigDecimal" name)
java.lang.Double (println "Found Double" name)
java.lang.Float (println "Found Float" name)
java.net.InetAddress (println "Found InetAddress" name)
java.lang.Integer (println "Found Integer" name)
java.util.Date (println "Found Date" name)
java.util.UUID (println "Found UUID" name)
java.math.BigInteger (println "Found BigInteger" name)
java.util.List (println "Found List" name)
java.util.Set (println "Found Set" name)
java.util.Map (println "Found Map" name))
But when I run this I get
java.lang.IllegalArgumentException: No matching clause: class java.util.UUID
This is what is thrown in when no suitable case is found. How do I match a class in a case clause?
+3
source to share
4 answers
Use a map instead of a form case
:
def case-map
{java.util.Set "Set",
java.math.BigInteger "BigInteger",
java.lang.Double "Double",
java.math.BigDecimal "BigDecimal",
java.util.List "List",
java.lang.Float "Float",
java.util.UUID "UUID",
java.lang.String "String",
java.lang.Integer "Integer",
java.nio.ByteBuffer "ByteBuffer",
java.lang.Boolean "Boolean",
java.net.InetAddress "InetAddress",
java.util.Date "Date",
java.util.Map "Map",
java.lang.Long "Long"})
(defn what-is [x] (str (case-map (type x)) " " x))
For instances:
(what-is (java.util.Date.))
"Date Mon Sep 22 08:17:55 BST 2014"
(what-is (java.util.UUID. 0 0))
"UUID 00000000-0000-0000-0000-000000000000"
Edit: The warning in @cgrand's answer against compiling AOT seems to apply to this solution as well.
+3
source to share
I ended up using multimethods
(defmulti get-row-data-for-class (fn [type-class name row] type-class))
(defmethod get-row-data-for-class java.lang.Boolean [type-class name row] (.getBool row name))
(defmethod get-row-data-for-class java.lang.Double [type-class name row] (.getDouble row name))
(defmethod get-row-data-for-class java.lang.Float [type-class name row] (.getFloat row name))
Then something like
(let [data (get-row-data-for-class type-class name row)])
0
source to share