Search code examples
clojuremultimethod

Can I dispatch a mutli-method on both Type AND properties in Clojure?


I have a method called "visualize" in my Clojure application which can supposedly render any part of my application. The problem I have is that some things in my application are Java classes and some are hashmaps, with fields internally marking the type of the map using the clojure :: idiom. I know I can use multimaps to dispatch on type or on some internal type, but how can I do it so that the same multimethod works on BOTH.


Solution

  • Create a dispatch function that both looks for maps with a special marker type and for Java classes.

    (defn visualize-dispatch [foo]
      (if (map? foo) 
        (:type foo)
        (class foo)))
    
    (defmulti visualize visualize-dispatch)
    
    (defmethod visualize String [s] 
      (println "Got a string" s))
    
    (defmethod visualize :banana [b] 
      (println "Got a banana that is" (:val b)))
    

    Then you can call visualize with either one of your Java classes or a map like {:type :banana :val "something"}.

    user> (visualize "bikini")
    Got a string bikini
    user> (visualize {:type :banana :val "speckled"})
    Got a banana that is speckled