Hacker News new | ask | show | jobs
by KingMob 3878 days ago
Just a slight addendum: Clojure multimethods can resolve to a concrete method implementation based on any function of their parameters.

So, in addition to single dispatch based on class (a la Java), you could also dispatch based on the classes of multiple parameters or on the value of the field 3 objects deep.

1 comments

kinda. The dispatch is on a single value and isa? isn't mapped over that single value if it happens to be a collection. This means you can dispatch on multiple concrete values in a collection or the isa? hierarchies of a single thing, but you don't get to isa? everything in the collection (unless you do it yourself over some limited set of things you care about; like you said, method dispatch is over ANY function).

This means that you can do something like

    (defmulti cares-about-a-and-c 
      "multimethod that cares about the first and third args" 
      (fn [a b c] [a c]))
    
    (defmethod cares-about-a-and-c [:alpha :gamma]
      [a b c]
      (prn "got :alpha and :gamma"))
    
    (defmethod cares-about-a-and-c [1 3]
      [a b c]
      (prn "got 1 and 3"))
but the following won't really work how you want it to:

    (defmethod cares-about-a-and-c [String String]
      [a b c]
      (prn "Got two things that match (isa? String)"))

   
    (cares-about-a-and-c "foo" nil "bar") ;; doesn't call our last method
You could, however, define something based on class and not isa? via your dispatch function:

    (defmulti cares-about-class-of-a-and-c
      ""
      (fn [a b c] (mapv class [a c])))

    (defmethod cares-about-class-of-a-and-c [String String]
      [a _ c]
      (println "Got the strings: " a " and " c))