Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Munich Clojure Workshop - 05 - Polymorphism

Munich Clojure Workshop - 05 - Polymorphism

Copyright © 2012-2014 Clojure Workshop Team: Maximilian Karasz, Jan Stępień, Marek Kubica, Oleksandr Petrov

Commercial use of complete work or parts of work is not allowed to anyone except for Clojure Workshop Team at whole or in parts.

Licensed under Creative Commons Attribution-NonCommercial 3.0: http://creativecommons.org/licenses/by-nc/3.0/

When using complete work or parts of work, explicit attribution is required.

Clojure Workshops

October 11, 2013
Tweet

More Decks by Clojure Workshops

Other Decks in Technology

Transcript

  1. (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
  2. (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
  3. (defn area [shape] (cond ...)) (defn perimeter [shape] (cond ...))

    (defn draw [shape] (cond ...)) ... Polymorphism Duplication of Flow Control Friday, October 11, 13
  4. Multimethods • Runtime polymorphism • Dispatch on arbitrary function •

    Values • Types • Metadata • Relationships amongst the above Friday, October 11, 13
  5. 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
  6. 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
  7. Multimethods (defmethod area ::rectangle [rectangle] (* (:w rectangle) (:h rectangle)))

    (defmethod area ::square [square] (* (:w square) (:h square))) Friday, October 11, 13
  8. 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
  9. Multimethods (area {type ::rectangle :w 10 :h 20}) ; =>

    200 (area {type ::square :w 10 :h 10}) ; => 100 Friday, October 11, 13
  10. Multimethods ((juxt + - * /) 2 3) ; =>

    [5 -1 6 2/3] Friday, October 11, 13
  11. 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
  12. Multimethods (triangle-type {:type ::unknown}) ; => IllegalArgumentException No method in

    multimethod 'triangle-type' for dispatch value: [:user/unknown 1] Friday, October 11, 13
  13. 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
  14. Protocols • Dispatch on type • High performance • 90%

    of the multimethods cases [1] [1] - http://clojure.org/protocols Friday, October 11, 13
  15. 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
  16. Protocols • Existing data structures • extend • extend-protocol •

    extend-type • New data structures • reify • defrecord Friday, October 11, 13
  17. extend (defprotocol Shape (area [shape]) (perimeter [shape])) (extend Shape Rectangle

    {:area #(* (.w %) (.h %)) :perimeter #(+ (* 2 (.w %)) (* 2 (.h %)))}) Friday, October 11, 13
  18. 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
  19. 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
  20. 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
  21. 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
  22. 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
  23. 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
  24. 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
  25. 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
  26. Exercises - Configuration • From Environment • (configuration-from-env) • From

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