Clojure:如何开启Java类的Case

时间:2014-09-21 18:25:29

标签: java clojure

我在clojure中有一个java类,它来自一个返回类的方法。我想打开这些,如下:

            (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))

但是当我运行这个时,我得到了

 java.lang.IllegalArgumentException: No matching clause: class java.util.UUID

当找不到匹配的案例时,抛出的是什么。我如何匹配case子句中的类?

4 个答案:

答案 0 :(得分:5)

你真的不能比cheshire做得更好,这基本上是对instance?的重复调用,如下所示:

(condp instance? x
  String :string
  Integer :int
  :unknown)

如果您不想关注子类型,并且只在x的类型上使用完全匹配,则可以改为使用(condp = (class x) ...)

答案 1 :(得分:3)

使用地图而不是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))

例如:

(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"

编辑:@cgrand's answer中针对AOT编译的警告似乎也适用于此解决方案。

答案 2 :(得分:1)

以下是如何欺骗这个问题:

=> (map #(case (class %)
           #=java.lang.String (str "Found String " %)
           #=java.lang.Long (str "Found Long " %))
     ["a" 42])
("Found String a" "Found Long 42")

但是由于类没有稳定的哈希码,所以不要在AOT编译的代码上使用它。

答案 3 :(得分:0)

我最终使用了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))

然后像

(let [data (get-row-data-for-class type-class name row)])