+ All Categories
Home > Documents > Clojure Protocols - GOTO Conference · data literals type properties example list singly-linked,...

Clojure Protocols - GOTO Conference · data literals type properties example list singly-linked,...

Date post: 31-Jul-2018
Category:
Upload: ngotu
View: 240 times
Download: 0 times
Share this document with a friend
160
Copyright 2007-2010 Relevance, Inc. This presentation is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License. See http://creativecommons.org/licenses/by-nc-sa/3.0/us/ Stuart Halloway [email protected] @stuarthalloway Clojure Protocols 1 Monday, October 4, 2010
Transcript

Copyright 2007-2010 Relevance, Inc. This presentation is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.

See http://creativecommons.org/licenses/by-nc-sa/3.0/us/

Stuart [email protected]@stuarthalloway

Clojure Protocols

1Monday, October 4, 2010

reading code

2

2Monday, October 4, 2010

atomic data typestype example java equivalentstring "foo" String

character \f Character

regex #"fo*" Pattern

a. p. integer 42 Int/Long/BigInteger

double 3.14159 Double

a.p. double 3.14159M BigDecimal

boolean true Boolean

nil nil null

ratio 22/7 N/A

symbol foo, + N/A

keyword :foo, ::foo N/A3

3Monday, October 4, 2010

data literals

type properties example

list singly-linked,insert at front (1 2 3)

vector indexed,insert at rear [1 2 3]

map key/value{:a 100 :b 90}

set key #{:a :b}

4

4Monday, October 4, 2010

(println "Hello World")

function call

fn call argsemantics:

structure: symbol string

list

5

5Monday, October 4, 2010

(defn greet "Returns a friendly greeting" [your-name] (str "Hello, " your-name))

function definition

define a fn fn namedocstring

arguments

fn body

6

6Monday, October 4, 2010

(defn greet "Returns a friendly greeting" [your-name] (str "Hello, " your-name))

it's all data

symbol symbolstring

vector

list

7

7Monday, October 4, 2010

(defn ^String greet "Returns a friendly greeting" [your-name] (str "Hello, " your-name))

metadata

prefix with ^ class name orarbitrary map

8

8Monday, October 4, 2010

what is OO?

9

9Monday, October 4, 2010

10

objects provide...

Object

10Monday, October 4, 2010

methods

11

Object

11Monday, October 4, 2010

polymorphism

12

Object

12Monday, October 4, 2010

types

13

Interface

Interface

Base Class

13Monday, October 4, 2010

namespaces

14

Interface

Interface

Base Class

14Monday, October 4, 2010

structure

15

Interface

Interface

Base Class

structxxxx yyyyzzzz

structxxxx yyyyzzzz

15Monday, October 4, 2010

uncontrolled mutation

16

Interface

Interface

Base Class

structxxxx yyyyzzzz

Uncontrolled Mutation

16Monday, October 4, 2010

clojure features are a la carte

17

17Monday, October 4, 2010

foundation

18

identity

generic dataaccessvalues

perception

functions

Varsstructxxxx yyyyzzzz

namespaces

typespolymorphism

structure

18Monday, October 4, 2010

superstructure

19

identity

generic dataaccessvalues

perception

functions

Varsstructxxxx yyyyzzzz

namespaces

typespolymorphism

structure

19Monday, October 4, 2010

in this talk

20

identity

generic dataaccessvalues

perception

functions

Varsstructxxxx yyyyzzzz

namespaces

typespolymorphism

structure

protocols

records

20Monday, October 4, 2010

records

21

21Monday, October 4, 2010

(defrecord Foo [a b c])-> user.Foo

defrecord

named typewith slots

22

22Monday, October 4, 2010

(defrecord Foo [a b c])-> user.Foo

defrecord

named typewith slots

(def f (Foo. 1 2 3))-> #'user/f positional

constructor

22

22Monday, October 4, 2010

(defrecord Foo [a b c])-> user.Foo

defrecord

named typewith slots

(def f (Foo. 1 2 3))-> #'user/f positional

constructor(:b f)-> 2 keyword access

22

22Monday, October 4, 2010

(defrecord Foo [a b c])-> user.Foo

defrecord

named typewith slots

(def f (Foo. 1 2 3))-> #'user/f positional

constructor(:b f)-> 2 keyword access

(class f)-> user.Foo

plain ol' class

22

22Monday, October 4, 2010

(defrecord Foo [a b c])-> user.Foo

defrecord

named typewith slots

(def f (Foo. 1 2 3))-> #'user/f positional

constructor(:b f)-> 2 keyword access

(class f)-> user.Foo

plain ol' class(supers (class f))-> #{clojure.lang.IObj clojure.lang.IKeywordLookup java.util.Map clojure.lang.IPersistentMap clojure.lang.IMeta java.lang.Object java.lang.Iterable clojure.lang.ILookup clojure.lang.Seqable clojure.lang.Counted clojure.lang.IPersistentCollection clojure.lang.Associative}

rasydht*

22

22Monday, October 4, 2010

(defrecord Foo [a b c])-> user.Foo

defrecord

named typewith slots

(def f (Foo. 1 2 3))-> #'user/f positional

constructor(:b f)-> 2 keyword access

(class f)-> user.Foo

plain ol' class(supers (class f))-> #{clojure.lang.IObj clojure.lang.IKeywordLookup java.util.Map clojure.lang.IPersistentMap clojure.lang.IMeta java.lang.Object java.lang.Iterable clojure.lang.ILookup clojure.lang.Seqable clojure.lang.Counted clojure.lang.IPersistentCollection clojure.lang.Associative}

rasydht*

*Rich abstracts so you don't have to22

22Monday, October 4, 2010

(def stu {:fname "Stu" :lname "Halloway" :address {:street "200 N Mangum" :city "Durham" :state "NC" :zip 27701}})

from maps...

23

data-oriented

23Monday, October 4, 2010

(def stu {:fname "Stu" :lname "Halloway" :address {:street "200 N Mangum" :city "Durham" :state "NC" :zip 27701}})

from maps...

23

(:lname stu)=> "Halloway"

keyword access

data-oriented

23Monday, October 4, 2010

(def stu {:fname "Stu" :lname "Halloway" :address {:street "200 N Mangum" :city "Durham" :state "NC" :zip 27701}})

from maps...

23

(:lname stu)=> "Halloway"

keyword access

(-> stu :address :city)=> "Durham"

nested access

data-oriented

23Monday, October 4, 2010

(def stu {:fname "Stu" :lname "Halloway" :address {:street "200 N Mangum" :city "Durham" :state "NC" :zip 27701}})

from maps...

23

(:lname stu)=> "Halloway"

keyword access

(-> stu :address :city)=> "Durham"

nested access

(assoc stu :fname "Stuart")=> {:fname "Stuart", :lname "Halloway", :address ...}

update

data-oriented

23Monday, October 4, 2010

(def stu {:fname "Stu" :lname "Halloway" :address {:street "200 N Mangum" :city "Durham" :state "NC" :zip 27701}})

from maps...

23

(:lname stu)=> "Halloway"

keyword access

(-> stu :address :city)=> "Durham"

nested access

(assoc stu :fname "Stuart")=> {:fname "Stuart", :lname "Halloway", :address ...}

update

(update-in stu [:address :zip] inc)=> {:address {:street "200 N Mangum", :zip 27702 ...} ...}

nestedupdate

data-oriented

23Monday, October 4, 2010

(defrecord Person [fname lname address])(defrecord Address [street city state zip])(def stu (Person. "Stu" "Halloway" (Address. "200 N Mangum" "Durham" "NC" 27701)))

...to records!

24

(:lname stu)=> "Halloway"

(-> stu :address :city)=> "Durham"

(assoc stu :fname "Stuart")=> :user.Person{:fname "Stuart", :lname"Halloway", :address ...}

(update-in stu [:address :zip] inc)=> :user.Person{:address {:street "200 N Mangum", :zip 27702 ...} ...}

24Monday, October 4, 2010

(defrecord Person [fname lname address])(defrecord Address [street city state zip])(def stu (Person. "Stu" "Halloway" (Address. "200 N Mangum" "Durham" "NC" 27701)))

...to records!

24

(:lname stu)=> "Halloway"

(-> stu :address :city)=> "Durham"

(assoc stu :fname "Stuart")=> :user.Person{:fname "Stuart", :lname"Halloway", :address ...}

(update-in stu [:address :zip] inc)=> :user.Person{:address {:street "200 N Mangum", :zip 27702 ...} ...}

object-oriented

24Monday, October 4, 2010

(defrecord Person [fname lname address])(defrecord Address [street city state zip])(def stu (Person. "Stu" "Halloway" (Address. "200 N Mangum" "Durham" "NC" 27701)))

...to records!

24

(:lname stu)=> "Halloway"

(-> stu :address :city)=> "Durham"

(assoc stu :fname "Stuart")=> :user.Person{:fname "Stuart", :lname"Halloway", :address ...}

(update-in stu [:address :zip] inc)=> :user.Person{:address {:street "200 N Mangum", :zip 27702 ...} ...}

still data-oriented:everything works

as before

object-oriented

24Monday, October 4, 2010

(defrecord Person [fname lname address])(defrecord Address [street city state zip])(def stu (Person. "Stu" "Halloway" (Address. "200 N Mangum" "Durham" "NC" 27701)))

...to records!

24

(:lname stu)=> "Halloway"

(-> stu :address :city)=> "Durham"

(assoc stu :fname "Stuart")=> :user.Person{:fname "Stuart", :lname"Halloway", :address ...}

(update-in stu [:address :zip] inc)=> :user.Person{:address {:street "200 N Mangum", :zip 27702 ...} ...}

still data-oriented:everything works

as before

object-oriented

type is therewhen you care

24Monday, October 4, 2010

protocols

25

25Monday, October 4, 2010

defprotocol

(defprotocol AProtocol "A doc string for AProtocol abstraction" (bar [a b] "bar docs") (baz [a] "baz docs"))

26

26Monday, October 4, 2010

named set of generic functions

defprotocol

(defprotocol AProtocol "A doc string for AProtocol abstraction" (bar [a b] "bar docs") (baz [a] "baz docs"))

26

26Monday, October 4, 2010

named set of generic functions

polymorphic on type of first argument

defprotocol

(defprotocol AProtocol "A doc string for AProtocol abstraction" (bar [a b] "bar docs") (baz [a] "baz docs"))

26

26Monday, October 4, 2010

named set of generic functions

polymorphic on type of first argument

defines fns in same namespace as protocol

defprotocol

(defprotocol AProtocol "A doc string for AProtocol abstraction" (bar [a b] "bar docs") (baz [a] "baz docs"))

26

26Monday, October 4, 2010

named set of generic functions

polymorphic on type of first argument

defines fns in same namespace as protocol

defprotocol

(defprotocol AProtocol "A doc string for AProtocol abstraction" (bar [a b] "bar docs") (baz [a] "baz docs"))

26

26Monday, October 4, 2010

extending a protocol

27

27Monday, October 4, 2010

inline

extending a protocol

27

27Monday, October 4, 2010

inline

extend protocol to multiple types

extending a protocol

27

27Monday, October 4, 2010

inline

extend protocol to multiple types

extend type to multiple protocols

extending a protocol

27

27Monday, October 4, 2010

inline

extend protocol to multiple types

extend type to multiple protocols

build directly from fns and maps

extending a protocol

27

27Monday, October 4, 2010

inline

extend protocol to multiple types

extend type to multiple protocols

build directly from fns and maps

extension happens in the protocol fns,not in the types

extending a protocol

27

27Monday, October 4, 2010

inline

extend protocol to multiple types

extend type to multiple protocols

build directly from fns and maps

extension happens in the protocol fns,not in the types

extending a protocol

27

27Monday, October 4, 2010

(deftype Bar [a b c] AProtocol (bar [this b] "Bar bar") (baz [this] (str "Bar baz " c)))

(def b (Bar. 5 6 7))

(baz b)

=> "Bar baz 7"

extending inline

28

28Monday, October 4, 2010

(baz "a")

java.lang.IllegalArgumentException: No implementation of method: :baz of protocol: #'user/AProtocol found for class: java.lang.String

(extend-type String AProtocol (bar [s s2] (str s s2)) (baz [s] (str "baz " s)))

(baz "a")

=> "baz a"

extend type to protocol(s)

29

29Monday, October 4, 2010

;; elided from clojure.java.io(extend-protocol Coercions String (as-file [s] (File. s)) (as-url [s] (URL. s)) File (as-file [f] f) (as-url [f] (.toURL f))

URI (as-url [u] (.toURL u)) (as-file [u] (as-file (as-url u))))

extending protocol to type(s)

30

30Monday, October 4, 2010

;; elided from clojure.java.io(extend InputStream IOFactory (assoc default-streams-impl :make-input-stream (fn [x opts] (BufferedInputStream. x)) :make-reader inputstream->reader))

(extend Reader IOFactory (assoc default-streams-impl :make-reader (fn [x opts] (BufferedReader. x))))

roll-your-own

31

31Monday, October 4, 2010

(let [x 42 r (reify AProtocol (bar [this b] "reify bar") (baz [this ] (str "reify baz " x)))] (baz r))

=> "reify baz 42"

reify

32

32Monday, October 4, 2010

(let [x 42 r (reify AProtocol (bar [this b] "reify bar") (baz [this ] (str "reify baz " x)))] (baz r))

=> "reify baz 42"

reify

instantiate an unnamed type

32

32Monday, October 4, 2010

(let [x 42 r (reify AProtocol (bar [this b] "reify bar") (baz [this ] (str "reify baz " x)))] (baz r))

=> "reify baz 42"

reify

instantiate an unnamed type

implement 0 or more protocols

or interfaces

32

32Monday, October 4, 2010

(let [x 42 r (reify AProtocol (bar [this b] "reify bar") (baz [this ] (str "reify baz " x)))] (baz r))

=> "reify baz 42"

reify

instantiate an unnamed type

implement 0 or more protocols

or interfaces

closes overenvironment

like fn

32

32Monday, October 4, 2010

the expressionproblem

33

33Monday, October 4, 2010

the expression problem

abstraction

concretion

A

34

34Monday, October 4, 2010

the expression problem

abstraction

concretion

A B

34

34Monday, October 4, 2010

the expression problem

abstraction

concretion

A B

A should be able to work with B's abstractions, and vice versa,without modification of

the original code

34

34Monday, October 4, 2010

is this really a problem?

abstraction

concretion

A B

just use interfaces for abstraction (??)

35

35Monday, October 4, 2010

example: arraylist vs.the abstractions

java.util.List

ArrayList

clojure.lang.Counted

clojure.lang.Seqable

?36

36Monday, October 4, 2010

example: string vs.the abstractions

java.util.List

String clojure.lang.Counted

clojure.lang.Seqable

?

37

37Monday, October 4, 2010

A can't inherit from B

38

38Monday, October 4, 2010

B is newer than A

A can't inherit from B

38

38Monday, October 4, 2010

B is newer than A

A is hard to change

A can't inherit from B

38

38Monday, October 4, 2010

B is newer than A

A is hard to change

we don't control A

A can't inherit from B

38

38Monday, October 4, 2010

B is newer than A

A is hard to change

we don't control A

A can't inherit from B

happens even within a single lib

38

38Monday, October 4, 2010

B is newer than A

A is hard to change

we don't control A

A can't inherit from B

happens even within a single lib

38

38Monday, October 4, 2010

some approachesto the expression

problem

39

39Monday, October 4, 2010

1. wrappers

java.util.List

String

java.util.Collection

40

strings are not collections

40Monday, October 4, 2010

NiftyString

so make a NiftyString that is

1. wrappers

java.util.List

String

java.util.Collection

40

strings are not collections

40Monday, October 4, 2010

wrappers = complexity

41

41Monday, October 4, 2010

ruin identity

wrappers = complexity

41

41Monday, October 4, 2010

ruin identity

ruin equality

wrappers = complexity

41

41Monday, October 4, 2010

ruin identity

ruin equality

cause nonlocal defects

wrappers = complexity

41

41Monday, October 4, 2010

ruin identity

ruin equality

cause nonlocal defects

wrappers = complexity

don't compose: AB + AC != ABC

41

41Monday, October 4, 2010

ruin identity

ruin equality

cause nonlocal defects

wrappers = complexity

don't compose: AB + AC != ABC

41

have bad names

41Monday, October 4, 2010

ruin identity

ruin equality

cause nonlocal defects

wrappers = complexity

don't compose: AB + AC != ABC

41

have bad names

41Monday, October 4, 2010

String

2. monkey patching

42

strings are not collections

java.util.List

java.util.Collection

42Monday, October 4, 2010

String

2. monkey patching

42

strings are not collections

java.util.List

java.util.Collection

sneak in and change them!

42Monday, October 4, 2010

String

2. monkey patching

common in e.g. rubynot possible in java

42

strings are not collections

java.util.List

java.util.Collection

sneak in and change them!

42Monday, October 4, 2010

monkey patching = complexity

43

43Monday, October 4, 2010

preserves identity (mostly)

monkey patching = complexity

43

43Monday, October 4, 2010

preserves identity (mostly)

ruins namespacing

monkey patching = complexity

43

43Monday, October 4, 2010

preserves identity (mostly)

ruins namespacing

causes nonlocal defects

monkey patching = complexity

43

43Monday, October 4, 2010

preserves identity (mostly)

ruins namespacing

causes nonlocal defects

monkey patching = complexity

43

forbidden in some languages

43Monday, October 4, 2010

preserves identity (mostly)

ruins namespacing

causes nonlocal defects

monkey patching = complexity

43

forbidden in some languages

43Monday, October 4, 2010

3. generic functions (CLOS)

String

map

reduce

count

44

44Monday, October 4, 2010

3. generic functions (CLOS)

String

map

reduce

count

polymorphism lives in the fns

44

44Monday, October 4, 2010

3. generic functions (CLOS)

don't touch existing implementation,

just use itString

map

reduce

count

polymorphism lives in the fns

44

44Monday, October 4, 2010

polymorphism a la carte

45

values polymorphismtypes

45Monday, October 4, 2010

polymorphism in the fns, not the types

polymorphism a la carte

45

values polymorphismtypes

45Monday, October 4, 2010

polymorphism in the fns, not the types

no "isa" requirement

polymorphism a la carte

45

values polymorphismtypes

45Monday, October 4, 2010

polymorphism in the fns, not the types

no "isa" requirement

no type intrusion necessary

polymorphism a la carte

45

values polymorphismtypes

45Monday, October 4, 2010

polymorphism in the fns, not the types

no "isa" requirement

no type intrusion necessary

polymorphism a la carte

45

values polymorphismtypes

45Monday, October 4, 2010

protocols = generic functions - arbitrary dispatch + speed + grouping

(and still powerful enough tosolve the expression problem!)

46

46Monday, October 4, 2010

where are we?

47

identity

generic dataaccessvalues

perception

functions

Varsstructxxxx yyyyzzzz

namespaces

typespolymorphism

structure

protocols,(multimethods)

defrecord,(deftype)

collections

47Monday, October 4, 2010

for more information

48

48Monday, October 4, 2010

communitymain Clojure site

http://clojure.org/

google group

http://groups.google.com/group/clojure

Clojure/core team

http://clojure.com

The conj

http://clojure-conj.org/

49

49Monday, October 4, 2010

free resourceslabrepl

http://github.com/relevance/labrepl

screencasts

http://clojure.blip.tv/

full disclojure screencasts

http://vimeo.com/channels/fulldisclojure

mark volkmann’s Clojure article

http://java.ociweb.com/mark/clojure/article.html

50

50Monday, October 4, 2010

thanks!

http://clojure.org

51

51Monday, October 4, 2010

extra

52

52Monday, October 4, 2010

example:rock/paper/

scissorshttp://rubyquiz.com/quiz16.html

53

53Monday, October 4, 2010

(defprotocol Player (choose [p]) (update-strategy [p me you]))

a player

54

54Monday, October 4, 2010

(defprotocol Player (choose [p]) (update-strategy [p me you]))

a player

pick :rock, :paper, or :scissors

54

54Monday, October 4, 2010

(defprotocol Player (choose [p]) (update-strategy [p me you]))

a player

pick :rock, :paper, or :scissors

return an updated Player based on what

you and I did

54

54Monday, October 4, 2010

(defrecord Stubborn [choice] Player (choose [_] choice) (update-strategy [this _ _] this))

stubborn player

55

55Monday, October 4, 2010

(defrecord Stubborn [choice] Player (choose [_] choice) (update-strategy [this _ _] this))

stubborn player

initialize with choice

55

55Monday, October 4, 2010

(defrecord Stubborn [choice] Player (choose [_] choice) (update-strategy [this _ _] this))

stubborn player

initialize with choice

play the choice

55

55Monday, October 4, 2010

(defrecord Stubborn [choice] Player (choose [_] choice) (update-strategy [this _ _] this))

stubborn player

initialize with choice

play the choice

never change

55

55Monday, October 4, 2010

(defrecord Mean [last-winner] Player (choose [_] (if last-winner last-winner (random-choice))) (update-strategy [_ me you] (Mean. (when (iwon? me you) me))))

mean player

56

56Monday, October 4, 2010

(defrecord Mean [last-winner] Player (choose [_] (if last-winner last-winner (random-choice))) (update-strategy [_ me you] (Mean. (when (iwon? me you) me))))

mean player

last thing thatworked for me

56

56Monday, October 4, 2010

(defrecord Mean [last-winner] Player (choose [_] (if last-winner last-winner (random-choice))) (update-strategy [_ me you] (Mean. (when (iwon? me you) me))))

mean player

last thing thatworked for me

play last winneror random

56

56Monday, October 4, 2010

(defrecord Mean [last-winner] Player (choose [_] (if last-winner last-winner (random-choice))) (update-strategy [_ me you] (Mean. (when (iwon? me you) me))))

mean player

last thing thatworked for me

play last winneror random

remember how/if I won

56

56Monday, October 4, 2010

deftype

57

57Monday, October 4, 2010

programming constructs are not like domain data

58

58Monday, October 4, 2010

use defrecord for domain information

59

59Monday, October 4, 2010

use defrecord for domain information

59

use deftype forprogramming constructs

59Monday, October 4, 2010

(deftype Bar [a b c])-> user.Bar

deftype

still a namedtype with slots

60

60Monday, October 4, 2010

(deftype Bar [a b c])-> user.Bar

deftype

still a namedtype with slots

(def o (Bar. 1 2 3))-> #'user/o constructor,

check

60

60Monday, October 4, 2010

(deftype Bar [a b c])-> user.Bar

deftype

still a namedtype with slots

(def o (Bar. 1 2 3))-> #'user/o constructor,

check

(.b o)-> 2 direct field

access only

60

60Monday, October 4, 2010

(deftype Bar [a b c])-> user.Bar

deftype

still a namedtype with slots

(def o (Bar. 1 2 3))-> #'user/o constructor,

check

(.b o)-> 2 direct field

access only

(class o)-> user.Bar still a

plain ol' class

60

60Monday, October 4, 2010

(deftype Bar [a b c])-> user.Bar

deftype

still a namedtype with slots

(def o (Bar. 1 2 3))-> #'user/o constructor,

check

(.b o)-> 2 direct field

access only

(class o)-> user.Bar still a

plain ol' class

(supers (class o))-> #{java.lang.Object} yoyo*

60

60Monday, October 4, 2010

(deftype Bar [a b c])-> user.Bar

deftype

still a namedtype with slots

(def o (Bar. 1 2 3))-> #'user/o constructor,

check

(.b o)-> 2 direct field

access only

(class o)-> user.Bar still a

plain ol' class

(supers (class o))-> #{java.lang.Object} yoyo*

*you're on your own60

60Monday, October 4, 2010

(into {} f)-> {:a 1, :b 2, :c 3, :extra 4}

the other constructor

(def f (Foo. 1 2 3 {:meta 1} {:extra 4}))-> #'user/f

(meta f)-> {:meta 1}

metadata

extra k/v pairs

61

61Monday, October 4, 2010

details

62

62Monday, October 4, 2010

type fields can be primitives

details

62

62Monday, October 4, 2010

type fields can be primitives

value-based equality and hash

details

62

62Monday, October 4, 2010

type fields can be primitives

value-based equality and hash

in-line methods defs can inline

details

62

62Monday, October 4, 2010

type fields can be primitives

value-based equality and hash

in-line methods defs can inline

keyword field lookups can inline

details

62

62Monday, October 4, 2010

type fields can be primitives

value-based equality and hash

in-line methods defs can inline

keyword field lookups can inline

protocols make interfaces (interop only)

details

62

62Monday, October 4, 2010

type fields can be primitives

value-based equality and hash

in-line methods defs can inline

keyword field lookups can inline

protocols make interfaces (interop only)

add java annotations (interop only)

details

62

62Monday, October 4, 2010

type fields can be primitives

value-based equality and hash

in-line methods defs can inline

keyword field lookups can inline

protocols make interfaces (interop only)

add java annotations (interop only)

details

deftype fields can be mutable (experts only)

62

62Monday, October 4, 2010

type fields can be primitives

value-based equality and hash

in-line methods defs can inline

keyword field lookups can inline

protocols make interfaces (interop only)

add java annotations (interop only)

details

deftype fields can be mutable (experts only)

62

62Monday, October 4, 2010

multimethods

63

63Monday, October 4, 2010

square.draw(canvas)

circle.draw(canvas)

p

f1(square, canvas)

f2(circle, canvas)

polymorphism

64

64Monday, October 4, 2010

square.draw(canvas)

circle.draw(canvas)

p() {return this.class;}

f1(square, canvas)

f2(circle, canvas)

p is just a function

65

65Monday, October 4, 2010

(defmulti blank? class)

clojure multimethods

dispatch byclass of first arg

66

66Monday, October 4, 2010

(defmulti blank? class)

clojure multimethods

dispatch byclass of first arg

(blank? "blah")-> No method in multimethod 'blank?' for dispatch value: class java.lang.String"

no impl yet!

66

66Monday, October 4, 2010

(defmulti blank? class)

clojure multimethods

dispatch byclass of first arg

(blank? "blah")-> No method in multimethod 'blank?' for dispatch value: class java.lang.String"

no impl yet!

(defmethod blank? String [s] (every? #(Character/isWhitespace %)) s))

add impls anytime

66

66Monday, October 4, 2010

(defmulti blank? class)

clojure multimethods

dispatch byclass of first arg

(blank? "blah")-> No method in multimethod 'blank?' for dispatch value: class java.lang.String"

no impl yet!

(defmethod blank? String [s] (every? #(Character/isWhitespace %)) s))

add impls anytime

(blank? "blah")-> false

66

66Monday, October 4, 2010

square.draw(canvas)

circle.draw(canvas)

p(this, that) {return this.class;}

f1(square, canvas)

f2(circle, canvas)

this isn’t special

67

67Monday, October 4, 2010

(fn [this, that] [(class this) (class that)])

(fn [square, canvas])

check all args

(fn [circle, canvas])

(fn [square, surface])

(fn [circle, surface])

68

68Monday, October 4, 2010

(fn [this, that] [(class this) (opaque? this) (class that)])

check arg twice

fn1fn2fn3fn4fn5fn6fn7fn8

69

69Monday, October 4, 2010

(defmulti coerce (fn [dest-class src-inst] [dest-class (class src-inst)]))

example: coerce

define amultimethod

based on dest (a class)

and src (an inst)

70

70Monday, October 4, 2010

(defmethod coerce [java.io.File String] [_ str] (java.io.File. str))

(defmethod coerce [Boolean/TYPE String] [_ str] (contains? #{"on" "yes" "true"} (.toLowerCase str)))

method impls

dispatch valueto match

args body

71

71Monday, October 4, 2010

(defmethod coerce :default [dest-cls obj] (cast dest-cls obj))

defaults

72

72Monday, October 4, 2010

(defmulti whatami? class)

(defmethod whatami? java.util.Collection [_] "a collection")

(whatami? (java.util.LinkedList.))-> "a collection"

(defmethod whatami? java.util.List [_] "a list")

(whatami? (java.util.LinkedList.))-> "a list"

class inheritance

most derivedtype wins

add methodsanytime

73

73Monday, October 4, 2010

(defmulti interest-rate :type)(defmethod interest-rate ::account [_] 0M)(defmethod interest-rate ::savings [_] 0.02)

name inheritance

double colon (::) is shorthand for resolvingkeyword into the current namespace, e.g.

::savings == :my.current.ns/savings

74

74Monday, October 4, 2010

(derive ::checking ::account)(derive ::savings ::acount)

(interest-rate {:type ::checking})-> 0M

deriving names

base namederived name

there is no ::checking method, so selectmethod for base name ::account

75

75Monday, October 4, 2010

multimethods lfu

function notes

prefer-method resolve conflicts

methods reflect on {dispatch, meth} pairs

get-method reflect by dispatch

remove-method remove by dispatch

prefers reflect over preferences

76

76Monday, October 4, 2010

multimethod elegance

77

77Monday, October 4, 2010

solve the expression problem

multimethod elegance

77

77Monday, October 4, 2010

solve the expression problem

no wrappers

multimethod elegance

77

77Monday, October 4, 2010

solve the expression problem

no wrappers

non-intrusive

multimethod elegance

77

77Monday, October 4, 2010

solve the expression problem

no wrappers

non-intrusive

open (add more at any time)

multimethod elegance

77

77Monday, October 4, 2010

solve the expression problem

no wrappers

non-intrusive

open (add more at any time)

namespaces work fine

multimethod elegance

77

77Monday, October 4, 2010

solve the expression problem

no wrappers

non-intrusive

open (add more at any time)

namespaces work fine

multimethod elegance

77

77Monday, October 4, 2010


Recommended