clojure - Converting defmulti to defprotocol -
is possible convert below code uses defprotocol
, defrecord
instead of defmulti
, defmethod
?
(defmulti test-multimethod (fn [keyword] keyword)) (defmethod test-multimethod :foo [a-map] "foo-method called") (defmethod test-multimethod :bar [a-map] "bar-method called") (defmulti perimeter (fn [shape] (:shape-name shape))) (defmethod perimeter :circle [circle] (* 2 math/pi (:radius circle))) (defmethod perimeter :rectangle [rectangle] (+ (* 2 (:width rectangle)) (* 2 (:height rectangle)))) (def some-shapes [{:shape-name :circle :radius 4} {:shape-name :rectangle :width 2 :height 2}]) (defmulti area (fn [shape] (:shape-name shape))) (defmethod area :circle [circle] (* math/pi (:radius circle) (:radius circle))) (defmethod area :rectangle [rectangle] (* (:width rectangle) (:height rectangle))) (defmethod perimeter :square [square] (* 4 (:side square))) (defmethod area :square [square] (* (:side square) (:side square))) (def more-shapes (conj some-shapes {:shape-name :square :side 4})) (for [shape more-shapes] (perimeter shape)) (for [shape more-shapes] (area shape))
yes, declare functions in protocol definition shape
, , define implementations in various record implementations square
, circle
, etc.
(defprotocol shape (area [this]) (perimeter [this])) (defrecord square [side] shape (area [this] (* (:side this) (:side this))) (perimeter [this] (* 4 (:side this)))) (defrecord rect [w l] shape (area [this] (* (:l this) (:w this))) (perimeter [this] (+ (:l this) (:l this) (:w this) (:w this)))) (def s (->square 4)) (def r (->rect 2 5)) (map area [s r]) ; '(16 10) (map :side [s r]) ; '(4 nil) (map :l [s r]) ; '(nil 5)
essentially oop (but immutable) if you're familiar that.
one nice thing defmulti implementation things though, can serialize , deserialize maps , use them as-is, without having reify them specific record class.
Comments
Post a Comment