Clojure Programming/Examples/API Examples/Multimethod

From Wikibooks, open books for an open world
Jump to navigation Jump to search

This page list examples of how to create Multi-Methods with the Clojure API.

defmulti[edit | edit source]

(defmulti area :Shape)
(defn rect [wd ht] {:Shape :Rect :wd wd :ht ht})
(defn circle [radius] {:Shape :Circle :radius radius})
(defmethod area :Rect [r]
    (* (:wd r) (:ht r)))
(defmethod area :Circle [c]
    (* (. Math PI) (* (:radius c) (:radius c))))
(defmethod area :default [x] :oops)
(def r (rect 4 13))
(def c (circle 12))
(area r)
-> 52
(area c)
-> 452.3893421169302
(area {})
-> :oops

This is an example of using multi-methods without using a hierarchy:

(defmulti rand-str 
  (fn [] (> (rand) 0.5)))

(defmethod rand-str true
  [] "true")

(defmethod rand-str false
  [] "false")

(for [x (range 5)] (rand-str))
-> ("false" "false" "true" "true" "false")


defmethod[edit | edit source]

(defmulti fib int) 
(defmethod fib 0 [_] 1) 
(defmethod fib 1 [_] 1) 
(defmethod fib :default [n] (+ (fib (- n 2)) (fib (- n 1)))) 
user=> (map fib (range 10)) 
(1 1 2 3 5 8 13 21 34 55)

Another example where the defmulti takes arguments and evaluates them before calling the defmethod

(defmulti multi-fun
  (fn [x y] (+ x y)))
(defmethod multi-fun 3 [x y]
  (print "Specialisation 3"))
(defmethod multi-fun :default [x y]
  (print "Generic " (+ x y)))
user=> (multi-fun 1 2)
Specialisation 3
user=> (multi-fun 3 4)
Generic 7