4

Let's say I have the following code:

(def m1 (java.util.HashMap.))
(def m2 (java.util.LinkedHashMap.))
(def m3 {})

I need a function that will allow me to detect maps that came from java, e.g.:

(map java-map? [m1 m2 m3]) ;; => (true true false)

Anything out of the box?

OlegTheCat
  • 4,443
  • 16
  • 24

2 Answers2

8

You can use map? to check if something implements IPersistentMap which is true for Clojure maps but not for java.utils.* maps:

(map? (java.util.HashMap.)) ;; => false
(map? (java.util.LinkedHashMap.)) ;; => false
(map? {}) ;; => true

To be more precise you should rather check if a given object meets some requirements (e.g. is persistent, immutable/mutable - map? will answer that specific question). There is no easy way to tell if you got a Java implementation of a map as you could get any other implementation from external library which might have a custom implementation of java.util.Map or extending one of the concrete implementations from java.util package.

Piotrek Bzdyl
  • 12,965
  • 1
  • 31
  • 49
  • 1
    Yes, was actually thinking about of usage of `map?`, but `(def java-map? (complement map?))` - this will give incorrect result on objects of other types: `(java-map? []) ;; => true` – OlegTheCat Apr 14 '16 at 15:44
  • 1
    Yes, you are correct, let me remove that part of the answer as it is incorrect. – Piotrek Bzdyl Apr 14 '16 at 15:46
  • I believe, there You also could use a `protocol` or `multimethods` to dispatch by input type – Roman Makhlin Apr 14 '16 at 15:51
4

i would do this:

user=> (defn java-map? [m] 
         (and (instance? java.util.Map m) 
              (not (map? m))))
#'user/java-map?

user=> (java-map? {})
false

user=> (java-map? (java.util.HashMap.))
true

user=> (java-map? [])
false

so you just check that it implements core java's Map interface, but not being a clojure's persistent map.

leetwinski
  • 17,408
  • 2
  • 18
  • 42