Skip to content
Multimethods
step 1/5

Reading — step 1 of 5

Learn

~1 min readPolymorphism

Multimethods dispatch on whatever you want — type, shape, value, computed key. More flexible than Java-style single dispatch.

(defmulti area :shape)

(defmethod area :circle [s]
    (* Math/PI (:radius s) (:radius s)))

(defmethod area :square [s]
    (* (:side s) (:side s)))

(defmethod area :rectangle [s]
    (* (:width s) (:height s)))

(defmethod area :default [s]
    (throw (Exception. (str "unknown shape: " (:shape s)))))

(area {:shape :circle :radius 5})       ; 78.54
(area {:shape :square :side 4})         ; 16

The :shape keyword is used as a dispatch function — its result picks the method.

Any function works as the dispatch:

(defmulti pay (fn [employee] (:type employee)))
(defmulti format-amount (fn [amount currency] currency))

Dispatch on multiple values:

(defmulti combine (fn [a b] [(class a) (class b)]))
(defmethod combine [String String] [a b] (str a b))
(defmethod combine [Number Number] [a b] (+ a b))

Hierarchies let you organize dispatch values:

(derive ::admin ::user)        ; admin is-a user
(defmethod greet ::user [u] (str "Hello, " (:name u)))
;; admin instance dispatches to ::user method (since admin derives from user)

Use multimethods when type-class-like behavior with open extension matters more than performance. For tighter, more focused polymorphism, use protocols (next lesson).

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…