Slide 1

Slide 1 text

Polymorphism in Clojure Friday, October 11, 13

Slide 2

Slide 2 text

(def circle {:type ::circle :r 10}) (def rectan {:type ::rectangle :w 10 :h 20}) (def square {:type ::square :w 10 :h 10}) (defn area [{type :type :as shape}] (cond (= type ::circle) (* (. Math PI) (:r shape) (:r shape)) (= type ::rectangle) (* (:w shape) (:h shape)) (= type ::square) (* (:w shape) (:h shape))) Polymorphism Friday, October 11, 13

Slide 3

Slide 3 text

(defn area [{type :type :as shape}] (cond (= type ::circle) (* (. Math PI) (:r shape) (:r shape)) (= type ::rectangle) (* (:w shape) (:h shape)) (= type ::square) (* (:w shape) (:h shape))) Polymorphism Not Declarative Friday, October 11, 13

Slide 4

Slide 4 text

(defn area [shape] (cond ...)) (defn perimeter [shape] (cond ...)) (defn draw [shape] (cond ...)) ... Polymorphism Duplication of Flow Control Friday, October 11, 13

Slide 5

Slide 5 text

Polymorphism • Multimethods • Protocols Friday, October 11, 13

Slide 6

Slide 6 text

Polymorphism • Multimethods • Protocols Friday, October 11, 13

Slide 7

Slide 7 text

Multimethods • Runtime polymorphism • Dispatch on arbitrary function • Values • Types • Metadata • Relationships amongst the above Friday, October 11, 13

Slide 8

Slide 8 text

Multimethods (defmulti function-name "This is the docstring" dispatch-fn) Friday, October 11, 13

Slide 9

Slide 9 text

Multimethods (defmethod function-name match-1 [this] ...) (defmethod function-name match-2 [this] ...) Friday, October 11, 13

Slide 10

Slide 10 text

Multimethods (defmulti area :type) (defmethod area ::circle [circle] (* Math/PI (:r circle) (:r circle))) (defmethod area ::rectangle [rectangle] (* (:w rectangle) (:h rectangle))) (defmethod area ::square [square] (* (:w square) (:h square))) Friday, October 11, 13

Slide 11

Slide 11 text

Multimethods (area {:type ::circle :r 10}) ; => 314.1592 (area {:type ::rectangle :w 10 :h 20}) ; => 200 (area {:type ::square :w 10 :h 10}) ; => 100 Friday, October 11, 13

Slide 12

Slide 12 text

Multimethods (defmethod area ::rectangle [rectangle] (* (:w rectangle) (:h rectangle))) (defmethod area ::square [square] (* (:w square) (:h square))) Friday, October 11, 13

Slide 13

Slide 13 text

Multimethods (derive ::square ::rectangle) (defmulti area :type) (defmethod area ::circle [circle] (* Math/PI (:r circle) (:r circle))) (defmethod area ::rectangle [rectangle] (* (:w rectangle) (:h rectangle))) Friday, October 11, 13

Slide 14

Slide 14 text

Multimethods (area {type ::rectangle :w 10 :h 20}) ; => 200 (area {type ::square :w 10 :h 10}) ; => 100 Friday, October 11, 13

Slide 15

Slide 15 text

Multimethods ((juxt + - * /) 2 3) ; => [5 -1 6 2/3] Friday, October 11, 13

Slide 16

Slide 16 text

Multimethods • Which triangle? • Equilateral • Isosceles • Scalene Friday, October 11, 13

Slide 17

Slide 17 text

Multimethods (defmulti triangle-type (juxt :type unique-sides)) (defmethod triangle-type [::triangle 1] [_] :equilateral) (defmethod triangle-type [::triangle 2] [_] :isosceles) (defmethod triangle-type [::triangle 3] [_] :scalene) Friday, October 11, 13

Slide 18

Slide 18 text

Multimethods (triangle-type {:type ::unknown}) ; => IllegalArgumentException No method in multimethod 'triangle-type' for dispatch value: [:user/unknown 1] Friday, October 11, 13

Slide 19

Slide 19 text

Multimethods (defmethod triangle-type :default [_] :unknown) (triangle-type {:type ::unknown}) ; => :unknown Friday, October 11, 13

Slide 20

Slide 20 text

Multimethods (defmulti area type) (defmethod area Circle [circle] (* Math/PI (.r circle) (.r circle))) (defmethod area Rectangle [rectangle] (* (.w rectangle) (.h rectangle))) (defmethod area Square [square] (* (.w square) (.h square))) Friday, October 11, 13

Slide 21

Slide 21 text

Polymorphism • Multimethods • Protocols Friday, October 11, 13

Slide 22

Slide 22 text

Protocols • Dispatch on type • High performance • 90% of the multimethods cases [1] [1] - http://clojure.org/protocols Friday, October 11, 13

Slide 23

Slide 23 text

Protocols (defprotocol P "This is the docstring for P" (foo [a] "this function foos") (bar [a b] "this one bars") (baz [a] [a b] [a b c] "this one baz a lot")) Friday, October 11, 13

Slide 24

Slide 24 text

Protocols (defprotocol Shape (area [shape]) (perimeter [shape])) Friday, October 11, 13

Slide 25

Slide 25 text

Protocols • Existing data structures • extend • extend-protocol • extend-type • New data structures • reify • defrecord Friday, October 11, 13

Slide 26

Slide 26 text

Protocols Existing Classes Friday, October 11, 13

Slide 27

Slide 27 text

extend (defprotocol Shape (area [shape]) (perimeter [shape])) (extend Shape Rectangle {:area #(* (.w %) (.h %)) :perimeter #(+ (* 2 (.w %)) (* 2 (.h %)))}) Friday, October 11, 13

Slide 28

Slide 28 text

extend-protocol (defprotocol Shape (area [shape]) (perimeter [shape])) (extend-protocol Shape Rectangle (area [rect] ...) (perimeter [rect] ...) Circle (area [circle] ...) (perimeter [circle] ...)) Friday, October 11, 13

Slide 29

Slide 29 text

extend-type (defprotocol Shape (area [shape]) (perimeter [shape])) (defprotocol Drawable (draw [shape])) (defprotocol Transformable (rotate [shape]) (translate [shape])) (extend-type Rectangle Shape (area [shape] …) (perimeter [shape] …) Drawable (draw [shape] …) Transformable (rotate [shape] …) (translate [shape] …)) Friday, October 11, 13

Slide 30

Slide 30 text

Protocols New Implementations Friday, October 11, 13

Slide 31

Slide 31 text

reify (defprotocol Shape (area [shape]) (perimeter [shape])) (reify Shape (area [triangle] (* ½ (.height triangle) (.base triangle))) (perimeter [triangle] (+ (.a triangle) (.b triangle) (.c triangle)))) Friday, October 11, 13

Slide 32

Slide 32 text

defrecord (defprotocol Shape (area [shape]) (perimeter [shape])) (defrecord Parallelogram [h b] Shape (area [para] (* (.b para) (.h para))) (perimeter [para] (* 2 (+ (.b para) (.h para))))) Friday, October 11, 13

Slide 33

Slide 33 text

Protocols • Not Monkeypatching • Not wrapping Friday, October 11, 13

Slide 34

Slide 34 text

Exercises - Message logging (log {:type :init :from 1 :to 2}) "Host 1 initiating conversation with host 2" (log {:type :message :from 3 :to 4 :message "hello"}) "Host 3 to host 4: hello" (log {:type :file :from 5 :to 6 :file {:name "image.jpg" :payload "payload"}}) "Host 5 sending file image.jpg to host 6" (log {:type :end :from 7 :to 8}) "Host 7 closed the conversation with host 8" Friday, October 11, 13

Slide 35

Slide 35 text

Exercises - Bounded Queue • Enqueue • enqueue [] e - [e] • enqueue [elements] e - [elements e] • enqueue [elements] e - RuntimeException "Queue is full" • Dequeue • dequeue [] - RuntimeException "Queue is empty" • dequeue [elements e] - [e [elements]] • dequeue [elements e] - [e [elements]] Friday, October 11, 13

Slide 36

Slide 36 text

Exercises - Router • GET - Listing all resources • POST - Creating resource • PUT - Updating resource :id • DELETE - Removing resource :id • ANY - Not found GET /users, POST /users, PUT /users/1, DELETE /users/1 GET /items, POST /items, PUT /items/1, DELETE /items/1 {:uri "/url" :method :get :params {:id 1}} Friday, October 11, 13

Slide 37

Slide 37 text

Exercises - Beverages Represent this information using protocols • Water: 0% alcohol, 0% sugar, 0% carbs • Soda: 0% alcohol, 50% sugar, 10% carbs • Beer: 5% alcohol, 0% sugar, 15% carbs • Wine: 15% alcohol, 10% sugar, 2% carbs • Vodka: 40% alcohol, 0% sugar, 0% carbs Friday, October 11, 13

Slide 38

Slide 38 text

Exercises - Configuration • From Environment • (configuration-from-env) • From Map • (configuration-from-map {:port ... :name ...}) (defprotocol Configuration (port []) (name [])) Friday, October 11, 13