Slide 1

Slide 1 text

Continuation-Passing Style and Design By Contract by. 2019/3/19 try! Swift Pre Talks 2019 1

Slide 2

Slide 2 text

takasek @takasek Works OSS: ActionClosurable౳ App: PasteTheType Articles ʮίϯύΠϧΤϥʔ΍ϥϯλΠϜΤϥʔΛ௚͍ͯ͘͠ ͚ͩͰiOSΞϓϦͷ࡞Γํ͕Θ͔ΔϓϩδΣΫτʯ ʮ͓લΒ͕ModelͱݺͿΞϨΛͳΜͱݺͿ΂͖͔ʯ ʮiOSΞϓϦઃܭύλʔϯೖ໳ʯʢڞஶʣ 2

Slide 3

Slide 3 text

ʮiOSΞϓϦઃܭύλʔϯೖ໳ʯ ON SALE!! https://peaks.cc/takasek/iOS_architecture takasek୲౰ষ Chap 1ʮTo designʯ Chap 2ʮBefore applying patterns to your designʯ Chap 3ʮDesigning swiftyʯ Chap 4ʮOverview through history of architecturesʯ 3

Slide 4

Slide 4 text

Continuation- Passing Style (CPS) 4

Slide 5

Slide 5 text

// Without CPS func doSomething(i: Int) -> String { sleep(100) return "\(i)" } // With CPS func doSomething(i: Int, completion: @escaping (String) -> Void) { DispatchQueue.global().async { sleep(100) completion("\(i)") } } 5

Slide 6

Slide 6 text

! 6

Slide 7

Slide 7 text

func doSomething( i: Int, completion: @escaping (String) -> Void ) This interface isn't the best 7

Slide 8

Slide 8 text

ʮI know what you meanʯ 8

Slide 9

Slide 9 text

ʮAbout Callback Hell, huh?ʯ 9

Slide 10

Slide 10 text

Nop. 10

Slide 11

Slide 11 text

Design By Contract 11

Slide 12

Slide 12 text

Design By Contract The idea to construct reliable system introduced by Bertrand Meyer 12

Slide 13

Slide 13 text

Design By Contract Asserts; • Preconditionɿ a caller should ensure it. described by Argument Type or so on. • Postconditionɿ a callee should ensure it. described by Return Type or so on. If precondition is violated, throw Exception. 13

Slide 14

Slide 14 text

For example, func half(of i: Int) throws -> Int { assert(i.isMultiple(of: 2)) if !i.isMultiple(of: 2) { throw Error.isOdd } return i / 2 } • Precondition: • accepts Int. • accepts Even. (not describable as type) • Postcondition: returns Int. • Exception: thrown if the argument is odd. 14

Slide 15

Slide 15 text

Swifty type system helps Design by Contract. 15

Slide 16

Slide 16 text

By the way, 16

Slide 17

Slide 17 text

func half(of i: Int) throws -> Int { if !i.isMultiple(of: 2) { throw Error.isOdd } return i / 2 } translate it to CPS. 17

Slide 18

Slide 18 text

func half(of i: Int, completion: (Int) -> Void) { if !i.isMultiple(of: 2) { return } completion(i / 2) } 18

Slide 19

Slide 19 text

19

Slide 20

Slide 20 text

OK, in the case of Odd value...? 20

Slide 21

Slide 21 text

21

Slide 22

Slide 22 text

Not called...? 22

Slide 23

Slide 23 text

23

Slide 24

Slide 24 text

completion hadn't be called 24

Slide 25

Slide 25 text

func half(of i: Int, completion: (Int) -> Void) { if !i.isMultiple(of: 2) { return // ! } completion(i / 2) } 25

Slide 26

Slide 26 text

enum Result { case success(T) case error(Error) } func half(of i: Int, completion: (Result) -> Void) { if !i.isMultiple(of: 2) { return // ! } completion(.success(i / 2)) } 26

Slide 27

Slide 27 text

enum Result { case success(T) case error(Error) } func half(of i: Int, completion: (Result) -> Void) { if !i.isMultiple(of: 2) { completion(.error(.isOdd)) // } completion(.success(i / 2)) } 27

Slide 28

Slide 28 text

Okay, check again! 28

Slide 29

Slide 29 text

29

Slide 30

Slide 30 text

Called twice...? 30

Slide 31

Slide 31 text

func half(of i: Int, completion: (Result) -> Void) { if !i.isMultiple(of: 2) { completion(.error(.isOdd)) // ! } completion(.success(i / 2)) } 31

Slide 32

Slide 32 text

func half(of i: Int, completion: (Result) -> Void) { if !i.isMultiple(of: 2) { completion(.error(.isOdd)) return // ! } completion(.success(i / 2)) } 32

Slide 33

Slide 33 text

CPS avoids benefits of Static Typing 33

Slide 34

Slide 34 text

ͳͥͳͷ͔ ໭Γ஋ͷܕʹΑͬͯ ࣄޙ৚݅ΛදݱͰ͖ͳ͍͔Β (T, (U) -> Void) -> Void Void͸࠷ऑͷࣄޙ৚݅ 34

Slide 35

Slide 35 text

Ͳ͏͢Ε͹͍͍͔ ໭Γ஋ͷܕʹΑͬͯ ࣄޙ৚݅Λදݱ͢Ε͹͍͍ (T) -> XXX ʮ͍ͣΕ݁Ռ͕ಘΒΕΔʯ͜ͱΛܕ෇͚ͰࣔͤΕ͹ɺ ඇಉظॲཧͰ΋໭Γ஋Λػೳͤ͞ΒΕΔ 35

Slide 36

Slide 36 text

func half(of i: Int) -> RxSwift.Single { if !i.isMultiple(of: 2) { return .error(Error.isOdd) } return .just(i / 2) } ͜ΕͳΒ੩తܕ෇͚ͷԸܙΛड͚ͭͭɺ ʮඇಉظͰ͋Δ͜ͱʯΛදݱͰ͖Δ 36

Slide 37

Slide 37 text

• Promise(Future) ύλʔϯ • PromiseK • Hydra • RxSwift • etc • async/await • comming soon in Swift 5.x!? • ͜ͷݴޠ࢓༷Λϕʔεʹ Future ܕΛߏஙՄೳ CPSΛશ໘తʹஔ͖͔͑Մೳ͔ͱ͍͏ͱ೉͍͕͠ɺ બ୒ࢶΛ஌ͬͨ͏͑ͰύλʔϯΛબͼ͍ͨ 37

Slide 38

Slide 38 text

݁࿦ ɾਓؒ͸ϛεΛ͠·͢ ɾϛεΛ͢Δલʹɺ ද໌ΛίϯύΠϥ͕෼͔ΔܗͰॻ͚ͳ͍͔ ҙࣝ͠ͳ͕Βઃܭ͠·͠ΐ͏ 38

Slide 39

Slide 39 text

͓·͚ ͱͯ΋5෼Ͱ͸ޠΓ͖Εͳ͍࿩ 39

Slide 40

Slide 40 text

ʮද໌ʯʹ͍ͭͯͷิ଍ • Ҿ਺ɾ໭Γ஋ͷܕ͚͕ͩද໌Ͱ͸ͳ͍ͱݴ͚ͬͨΕͲ… • assert ͚ͩͰͳ͘ɺSwiftͰݴ͑͹ generics ΍ conditional conformance΋ද໌ͷํ๏ • ΂ͭʹɺίϯύΠϥղऍෆೳͳද໌͸ྑ͘ͳ͍…Θ͚Ͱ͸ͳ͍ • දݱྗΛ্͛Δͱֶशίετɾෳࡶੑ͕ϖΠ͠ͳ͍͜ͱ΋ଟ͍ͷͰɺͦ͜͸όϥϯε • ͨͱ͑͹ɺڽͬͨprotocolͷwhere۟ɺৗਓʹཧղग़དྷΔ͔ͬͯݴΘΕΔͱݫ͍͠ΑͶ… ɹ 40

Slide 41

Slide 41 text

ิ଍ͷิ଍ ٯʹݴ͑͹ɺ ܖ໿ʹΑΔઃܭ͸ ݴޠΛ໰Θͣద༻Մೳͳ֓೦Ͱ͢ t_wada͞ΜʹΑΔ ͋͑ͯPHPΛϕʔεʹͨ͠εϥΠυ PHPer͡Όͳͯ͘΋ΦεεϝͰ͢ https://speakerdeck.com/twada/php- conference-2016 41

Slide 42

Slide 42 text

ʮܧଓ౉͠ʯʹ͍ͭͯͷิ଍ • ࣮͸ async/await͸ʮ಺෦తͳCPSม׵ʯͦͷ΋ͷͱ͍͑·͢ Continuation Passing Style Revisited – Fabulous Adventures In Coding https://blogs.msdn.microsoft.com/ericlippert/2010/10/21/ continuation-passing-style-revisited-part-one/ ͦͷ࿨༁ matarillo.com: ܧଓ౉͠ελΠϧ(CPS)ͱඇಉظߏจ(async/await) https://matarillo.com/general/cps 42

Slide 43

Slide 43 text

Swiftͷ async/await ͱ ܧଓͱ Future ͷؔ܎ Chris Lattnerͷproposal2ʹΑΔͱɺ • ଞͷݴޠͰ͸ Future ͕·ͣ͋ͬͯɺͦͷ্ʹasync/await͕৐͔͍ͬͬͯΔ • Swiftͷasync/awaitͷઃܭͰ͸ͦΕΛલఏͱ͸ͤͣɺܧଓΛͦͷ··ѻ͏खஈΛ࿐ग़͍ͤͯ͞ Δ • ͱ͸͍͑ Future ͱ͍͏ܕ෇͚͞Εͨঢ়ଶͰѻ͏ΠϯλϑΣʔε΋ߏஙՄೳͰ͢Αɺͱ͍͏͜ͱ 2 https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619 yimajo͞Μͷʮasync/awaitݚڀಡຊʯ΋͋ΘͤͯͲ͏ͧ 43

Slide 44

Slide 44 text

ؔ࿈ɿʮܖ໿ʹΑΔઃ ܭʯΛΩʔϫʔυͰ֦ ு͢Δ࿩ ʮܖ໿ʹΑΔઃܭʯʹ͍ͭͯৄղ͞Ε ͍ͯΔʮΦϒδΣΫτࢦ޲ೖ໳ʯʹ ͸ɺ ඇಉظʢฒߦʣॲཧΛ΋ͱʹ֦ுͨ͠ ৔߹ͷܖ໿ͷϙϦγʔʹ͍ͭͯͷٞ࿦ ΋͋Γ·͢ ໘ന͍Αʂ 44