Clojure case statement with classes

Viewed 3884

I want to switch on the class of a given object in order to encode it.

(defn encoded-msg-for [msg]
  (case (class msg)
    java.lang.Double   (encode-double msg)
    java.lang.String   (encode-str msg)
    java.lang.Long   (encode-int msg)
    java.lang.Boolean  (encode-bool msg)
    clojure.lang.PersistentArrayMap (encode-hash msg)
    clojure.lang.PersistentVector (encode-vec msg)
    nil "~"
  )
 )

When I call (encoded-msg-for {}), it returns No matching clause: class clojure.lang.PersistentArrayMap

What is odd is that putting the cases into a hash-map (with the classes as keys and strings as values) works perfectly well.

Also, (= (class {}) clojure.lang.PersistentArrayMap) is true. What comparison is happening here and how can I switch either on the class of the object itself or (better) something in its hierarchy?

3 Answers

If you are looking for an alternative way to achieve this, take a peek at condp:

(condp = (type {})
  clojure.lang.PersistentArrayMap :one
  clojure.lang.PersistentVector :many
  :unknown) ;; => :one
Related