Save 37% off PRO during our Black Friday Sale! »

iOSDC2018.pdf

06641ec93c5914e0db74cddff2ec6004?s=47 Yuki Yasoshima
August 31, 2018
1.2k

 iOSDC2018.pdf

06641ec93c5914e0db74cddff2ec6004?s=128

Yuki Yasoshima

August 31, 2018
Tweet

Transcript

  1. 4XJGUͷίʔυ͔Β ঢ়ଶભҠਤΛࣗಈͰੜ੒͠ ܧଓతʹϝϯςφϯε͠΍͘͢͢Δ J04%$+BQBO IUUQTHJUIVCDPNPCKFDUJWFBVEJPJ04%$

  2. εςʔτϚγϯ ʢ༗ݶΦʔτϚτϯʣ ঢ়ଶͱભҠͱಈ࡞ͷ૊Έ߹Θ͔ͤΒͳΔ ৼΔ෣͍ͷϞσϧ

  3. ྫɿυΞͷ։ด

  4. ด͍ͯ͡Δ ։͍͍ͯΔ ։͘ ด͡Δ

  5. ด͍ͯ͡Δ ։͍͍ͯΔ ։͘ ด͡Δ ঢ়ଶ ঢ়ଶ

  6. ด͍ͯ͡Δ ։͍͍ͯΔ ։͘ ด͡Δ ಈ࡞ ಈ࡞

  7. ด͍ͯ͡Δ ։͍͍ͯΔ ։͘ ด͡Δ ભҠ ભҠ

  8. ด͍ͯ͡Δ ։͍͍ͯΔ ։͘ ด͡Δ

  9. ด͍ͯ͡Δ ։͍͍ͯΔ ։͘ ด͡Δ υΞͷ։ดͷঢ়ଶભҠਤ

  10. ৼΔ෣͍Λίʔυʹ͢Δ

  11. εςʔτύλʔϯ Ϋϥεʹڞ௨ͷΠϯλʔϑΣʔεΛఆٛͯ͠ ΠϯελϯεΛೖΕସ͑ͯৼΔ෣͍Λม͑Δ

  12. ໰୊ શମͷભҠ͕Θ͔Γʹ͍͘ ࣗ༝౓͕ߴ͗͢Δ Ϋϥε͕૿͑͗͢Δ

  13. ղܾࡦ ঢ়ଶભҠਤΛ࡞Δ

  14. ܧଓతʹίʔυͱਤΛ߹ΘͤΔͷ͕େม ໰୊

  15. VJqPX IUUQTHJUIVCDPNIJSPLJEBJDIJVJqPX [࠷ॳʹ] Ϣʔβʔ͕ݟΔ΋ͷΛॻ͖·͢ɻ -- Ϣʔβʔ͕͢ΔߦಈΛॻ͖·͢ɻ [࣍ʹ] Ϣʔβʔ͕ݟΔ΋ͷ -- Ϣʔβʔ͕͢Δ͜ͱ̍

    ==> ͦͷ݁Ռ̍ Ϣʔβʔ͕͢Δ͜ͱ̎ ==> ͦͷ݁Ռ̎ [ͦͷ݁Ռ̍] ݁Ռ [ͦͷ݁Ռ̎] ݁Ռ
  16. "45 IUUQTTQFBLFSEFDLDPNLJTIJLBXBLBUTVNJBTUNFUBQSPHSBNNJOHJOTXJGU AST meta-programming in Swift try! Swift Tokyo 2018

    Abstract Syntax Tree
  17. 'MPX(SBQI 4XJGUͷεςʔτϚγϯϥΠϒϥϦ IUUQTHJUIVCDPNPCKFDUJWFBVEJP4XJGU'MPX(SBQI

  18. 'MPX(SBQI%PU$POWFSUFS 'MPX(SBQIͰॻ͔Εͨίʔυ͔Β (SBQIWJ[ͷϑΝΠϧܗࣜʹॻ͖ग़͢ ίϚϯυϥΠϯπʔϧ IUUQTHJUIVCDPNPCKFDUJWFBVEJP'MPX(SBQI%PU$POWFSUFS

  19. digraph { graph [label = "Door", labelloc = "t", labeljust

    = "l", fontcolor = "#333333", rankdir = "TB", fontname = "Osaka-Mono", fontsize = "12", charset = "UTF-8"] node [fontcolor = "#333333", fillcolor = "#F9F9F9", fontname = "Osaka-Mono", style = "solid,filled", fontsize = "10", color = "#CCCCCC"] edge [fontcolor = "#333333", fontname = "Osaka-Mono", fontsize = "9", color = "#AAAAAA"] opened [shape = "record", label = "{opened|։͍͍ͯΔ}", color = "#BBBBBB"] closing [shape = "record", label = "{closing|ด͡Δ}", color = "#40C5EE"] closed [shape = "record", label = "{closed|ด͍ͯ͡Δ}", color = "#00D54B"] opening [shape = "record", label = "{opening|։͘}", color = "#40C5EE"] "opened" -> "closing" [style = "solid", color = "#99DEF3"] "closing" -> "closed" [style = "dashed", color = "#AAAAAA"] "closed" -> "opening" [style = "solid", color = "#99DEF3"] // // Door.swift // import FlowGraph // υΞͷঢ়ଶ class Door: FlowGraphType { private(set) var isOpen: Bool = false { didSet { print("isOpen \(self.isOpen)") if let handler = self.isOpenHandler { handler(self.isOpen) } } } var isOpenHandler: ((Bool) -> Void)? enum WaitingState { case closed case opened } enum RunningState { case opening case closing } enum EventKind { case open case close } typealias Event = (kind: EventKind, object: Door) private let graph: FlowGraph<Door> init() { let builder = FlowGraphBuilder<Door>() // ด͍ͯ͡Δ builder.add(waiting: .closed) { event in if case .open = event.kind { return .run(.opening, event) } else { return .stay } } // ։͍͍ͯΔ builder.add(waiting: .opened) { event in if case .close = event.kind { return .run(.closing, event) } else { return .stay } } %PPSTXJGU %PPSEPU %PPSTWH
  20. γΣϧεΫϦϓτͰ ΍͍ͬͯΔ͜ͱ

  21. $ brew install graphviz (SBQIWJ[ΛΠϯετʔϧ $POWFSUFSͷ४උ )PNFCSFXΛΠϯετʔϧʢͷ֬ೝʣ

  22. $ swift build -c release $ swift run -c release

    FlowGraphDotConverter ೖྗ͢ΔϑΝΠϧʢෳ਺ʣ--output ग़ྗ͢ΔϑΥϧμ $ dot -T svg ೖྗ͢Δύε -o ग़ྗ͢Δύε Ϗϧυ͢Δʢ4XJGU1BDLBHF.BOBHFSʣ 4XJGUϑΝΠϧΛղੳͯ͠(SBQIWJ[ͷܗࣜʹग़ྗ (SBQIWJ[Ͱਤʹม׵͢Δ $POWFSUFSͷ࣮ߦ
  23. 'MPX(SBQI

  24. 'MPX(SBQI%PPS DMPTFE PQFOFE DMPTJOH PQFOJOH &WFOU $VSSFOU

  25. 'MPX(SBQI%PPS DMPTFE PQFOFE 8BJUJOH4UBUF ଴ػ͢Δεςʔτ ֎෦͔ΒΠϕϯτΛड͚औ࣮ͬͯߦ͞ΕΔΫϩʔδϟΛ࣋ͭ &WFOU DMPTJOH ʢด͍ͯ͡Δʣ ʢ։͍͍ͯΔʣ

  26. 'MPX(SBQI%PPS DMPTFE PQFOFE Πϕϯτ 3VOOJOH4UBUF ॲཧΛ࣮ߦ͢Δεςʔτ 8BJUJOH4UBUF͔ΒΠϕϯτΛ ड͚औ࣮ͬͯߦ͞ΕΔ ΫϩʔδϟΛ࣋ͭ ଴ػ͢Δ͜ͱ͸Ͱ͖ͳ͍

    DMPTJOH PQFOJOH ʢ։͘ʣ ʢด͡Δʣ
  27. 'MPX(SBQI%PPS DMPTFE PQFOFE &WFOU &WFOU ֎෦͔Β$VSSFOUͷ8BJUJOH4UBUFʹ౉͞ΕΔ 8BUJOH4UBUF͔Β3VOOJOH4UBUFʹ౉͞ΕΔ $VSSFOU DMPTJOH

  28. DMPTFE PQFOFE $VSSFOU 'MPX(SBQI%PPS DMPTFEεςʔτʹ଴ػ͍ͯ͠Δ DMPTJOH PQFOJOH

  29. DMPTFE PQFOFE $VSSFOU 'MPX(SBQI%PPS PQFO PQFOΠϕϯτΛDVSSFOUͷεςʔτʹ౉͢ DMPTJOH PQFOJOH

  30. DMPTFE PQFOFE $VSSFOU 'MPX(SBQI%PPS PQFOJOHεςʔτʹભҠͯ͠։͘ॲཧΛ࣮ߦ͢Δ DMPTJOH PQFOJOH

  31. DMPTFE PQFOFE $VSSFOU 'MPX(SBQI%PPS PQFOFEεςʔτʹભҠͯ͠଴ػ͢Δ DMPTJOH PQFOJOH

  32. DMPTFE PQFOFE $VSSFOU 'MPX(SBQI%PPS DMPTF DMPTFΠϕϯτΛDVSSFOUͷεςʔτʹ౉͢ DMPTJOH PQFOJOH

  33. DMPTFE PQFOFE $VSSFOU 'MPX(SBQI%PPS DMPTJOHεςʔτʹભҠͯ͠ด͡ΔॲཧΛ࣮ߦ͢Δ DMPTJOH PQFOJOH

  34. DMPTFE PQFOFE $VSSFOU 'MPX(SBQI%PPS DMPTFEεςʔτʹભҠͯ͠଴ػ͢Δ DMPTJOH PQFOJOH

  35. DMPTFE PQFOFE $VSSFOU 'MPX(SBQI%PPS DMPTFEεςʔτʹભҠͯ͠଴ػ͢Δ DMPTJOH PQFOJOH DMPTF

  36. DMPTFE PQFOFE $VSSFOU 'MPX(SBQI%PPS DMPTFEεςʔτʹભҠͯ͠଴ػ͢Δ DMPTJOH PQFOJOH

  37. 'MPX(SBQIͷॻ͖ํ  ܕͷఆٛ  ઃܭΦϒδΣΫτͷੜ੒  εςʔτͷొ࿥  ࣮ߦΦϒδΣΫτͷੜ੒ 

    ΠϕϯτΛड͚औΔ
  38. ܕͷఆٛ

  39. 'MPX(SBQI5ZQFʹద߹ͨ͠ܕΛఆٛ public protocol FlowGraphType { associatedtype WaitingState: Hashable associatedtype RunningState:

    Hashable associatedtype Event ... }
  40. class Door: FlowGraphType { enum WaitingState { case closed case

    opened } enum RunningState { case opening case closing } typealias Event = (kind: EventKind, object: Door) ... } 'MPX(SBQI5ZQFʹద߹ͨ͠ܕΛఆٛ
  41. class Door: FlowGraphType { enum WaitingState { case closed case

    opened } enum RunningState { case opening case closing } typealias Event = (kind: EventKind, object: Door) ... } ଴ػ͢ΔεςʔτͷܕʢFOVNਪ঑ʣ 'MPX(SBQI5ZQFʹ४ڌͨ͠ܕΛఆٛ
  42. class Door: FlowGraphType { enum WaitingState { case closed case

    opened } enum RunningState { case opening case closing } typealias Event = (kind: EventKind, object: Door) ... } ࣮ߦ͢ΔεςʔτͷܕʢFOVNਪ঑ʣ 'MPX(SBQI5ZQFʹ४ڌͨ͠ܕΛఆٛ
  43. class Door: FlowGraphType { enum WaitingState { case closed case

    opened } enum RunningState { case opening case closing } typealias Event = (kind: EventKind, object: Door) ... } ड͚औΔΠϕϯτͷܕʢͳΜͰ΋ʣ 'MPX(SBQI5ZQFʹ४ڌͨ͠ܕΛఆٛ enum EventKind { case open case close }
  44. ઃܭΦϒδΣΫτͷੜ੒

  45. let builder = FlowGraphBuilder<Door>() 'MPX(SBQI#VJMEFSΛੜ੒

  46. εςʔτͷొ࿥

  47. builder.add(waiting: .closed) { event in if case .open = event.kind

    { return .run(.opening, event) } else { return .stay } } 8BJUJOH4UBUFͷొ࿥
  48. builder.add(waiting: .closed) { event in if case .open = event.kind

    { return .run(.opening, event) } else { return .stay } } 8BJUJOH4UBUFͷొ࿥ ొ࿥͢Δεςʔτ໊
  49. builder.add(waiting: .closed) { event in if case .open = event.kind

    { return .run(.opening, event) } else { return .stay } } 8BJUJOH4UBUFͷొ࿥ ొ࿥͢ΔΫϩʔδϟ
  50. builder.add(waiting: .closed) { event in if case .open = event.kind

    { return .run(.opening, event) } else { return .stay } } ΠϕϯτΛड͚औΔ 8BJUJOH4UBUFͷొ࿥
  51. builder.add(waiting: .closed) { event in if case .open = event.kind

    { return .run(.opening, event) } else { return .stay } } 8BJUJOH4UBUFͷొ࿥ ผͷεςʔτʹભҠ͢Δ
  52. builder.add(waiting: .closed) { event in if case .open = event.kind

    { return .run(.opening, event) } else { return .stay } } 8BJUJOH4UBUFͷొ࿥ return .wait(.opened) ผͷεςʔτʹભҠ͢Δ
  53. builder.add(waiting: .closed) { event in if case .open = event.kind

    { return .run(.opening, event) } else { return .stay } } Կ΋͠ͳ͍ 8BJUJOH4UBUFͷొ࿥
  54. builder.add(running: .opening) { event in event.object.isOpen = true return .wait(.opened)

    } 3VOOJOH4UBUFͷొ࿥
  55. builder.add(running: .opening) { event in event.object.isOpen = true return .wait(.opened)

    } Կ͔ॲཧΛ͢Δ 3VOOJOH4UBUFͷొ࿥
  56. builder.add(running: .opening) { event in event.object.isOpen = true return .wait(.opened)

    } ผͷεςʔτʹભҠ͢Δ 3VOOJOH4UBUFͷొ࿥ ❇3VOOJOH4UBUFʹཹ·Δ͜ͱ͸Ͱ͖ͳ͍
  57. ࣮ߦΦϒδΣΫτͷੜ੒

  58. self.graph = builder.build(initial: .closed) 'MPX(SBQIΛੜ੒͢Δ

  59. self.graph = builder.build(initial: .closed) 'MPX(SBQIΛੜ੒͢Δ private let graph: FlowGraph<Door> ϓϩύςΟ

  60. self.graph = builder.build(initial: .closed) 'MPX(SBQIΛੜ੒͢Δ ࠷ॳʹ଴ػ͢Δεςʔτ

  61. Πϕϯτͷड͚औΓ

  62. ΠϕϯτΛड͚औΔ func run(_ kind: EventKind) { self.graph.run((kind, self)) }

  63. func run(_ kind: EventKind) { self.graph.run((kind, self)) } ΠϕϯτΛड͚औΔ ΠϕϯτΛ౉͢

  64. 'MPX(SBQI%PU$POWFSUFS

  65. 4PVSDF,JUUFO w 4PVSDF,JUΛίϚϯυϥΠϯͰ࢖͑ΔΑ͏ʹͨ͠ ϥΠϒϥϦ w 4XJGUͷίʔυΛղੳͯ͠ɺߏ଄ΛऔಘͰ͖Δ w 4PVSDF,JUUFO'SBNFXPSLΛΠϯϙʔτ͢Ε͹ɺ 4XJGUͷϥΠϒϥϦͱͯ͠΋࢖͑Δ

  66. w4USVDUVSF w4ZOUBY ղੳ͢Δػೳ

  67. 4USVDUVSF w πϦʔߏ଄Ͱղੳ͢Δ w DMBTT΍ؔ਺΍ม਺ͳͲͷߏ଄͕औಘͰ͖Δ w ίϝϯτͳͲ͸ແࢹ͞ΕΔ

  68. \ LFZEJBHOPTUJD@TUBHFTPVSDFEJBHOPTUJDTUBHFTXJGUQBSTF  LFZMFOHUI  LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZBDDFTTJCJMJUZTPVSDFMBOHTXJGUBDDFTTJCJMJUZJOUFSOBM

     LFZCPEZMFOHUI  LFZCPEZP⒎TFU  LFZFMFNFOUT< \ LFZLJOETPVSDFMBOHTXJGUTUSVDUVSFFMFNUZQFSFG  LFZMFOHUI  LFZP⒎TFU ^ >  LFZJOIFSJUFEUZQFT< \ LFZOBNF'MPX(SBQI5ZQF ^ >  LFZLJOETPVSDFMBOHTXJGUEFDMDMBTT  LFZMFOHUI  LFZOBNF%PPS  LFZOBNFMFOHUI  4USVDUVSF
  69. \ LFZEJBHOPTUJD@TUBHFTPVSDFEJBHOPTUJDTUBHFT LFZMFOHUI  LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZBDDFTTJCJMJUZTPVSDFMBOHTXJGUBDDFTTJCJ LFZCPEZMFOHUI

     LFZCPEZP⒎TFU  LFZFMFNFOUT< \ LFZLJOETPVSDFMBOHTXJGUTUSVDUVSFFMFN LFZMFOHUI  LFZP⒎TFU P⒎TFUͱMFOHUIͰ ཁૉͷจࣈྻͷҐஔ͕ औಘͰ͖Δ
  70. \ LFZEJBHOPTUJD@TUBHFTPVSDFEJBHOPTUJDTUBHFT LFZMFOHUI  LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZBDDFTTJCJMJUZTPVSDFMBOHTXJGUBDDFTTJCJ LFZCPEZMFOHUI

     LFZCPEZP⒎TFU  LFZFMFNFOUT< \ LFZLJOETPVSDFMBOHTXJGUTUSVDUVSFFMFN LFZMFOHUI  LFZP⒎TFU TVCTUSVDUVSFʹࢠͷཁૉͷ഑ྻ
  71. LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZBDDFTTJCJMJUZTPVSDFMBOHTXJGUBDDFTTJCJ LFZCPEZMFOHUI  LFZCPEZP⒎TFU  LFZFMFNFOUT<

    \ LFZLJOETPVSDFMBOHTXJGUTUSVDUVSFFMFN LFZMFOHUI  LFZP⒎TFU ^ >  LFZJOIFSJUFEUZQFT< LJOE͸ཁૉͷछྨ
  72. ΫϥεΛ୳͢

  73. // Door.swift // import FlowGraph // υΞͷঢ়ଶ class Door: FlowGraphType

    { private(set) var isOpen: Bool = false didSet { print("isOpen \(self.isOpen)") if let handler = self.isOpenHa handler(self.isOpen) } } } var isOpenHandler: ((Bool) -> Void)?
  74. LFZJOIFSJUFEUZQFT< \ LFZOBNF'MPX(SBQI5ZQF ^ >  LFZLJOETPVSDFMBOHTXJGUEFDMDMBTT  LFZMFOHUI 

    LFZOBNF%PPS  LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU  LFZSVOUJNF@OBNF@5U$@@NBJO@@%PPS  LFZTVCTUSVDUVSF< \ LFZBDDFTTJCJMJUZTPVSDFMBOHTXJGUBDDFTTJCJM LJOE͕DMBTT
  75. LFZJOIFSJUFEUZQFT< \ LFZOBNF'MPX(SBQI5ZQF ^ >  LFZLJOETPVSDFMBOHTXJGUEFDMDMBTT  LFZMFOHUI 

    LFZOBNF%PPS  LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU  LFZSVOUJNF@OBNF@5U$@@NBJO@@%PPS  LFZTVCTUSVDUVSF< \ LFZBDDFTTJCJMJUZTPVSDFMBOHTXJGUBDDFTTJCJM P⒎TFUͱMFOHIͰ ΫϥεͷҐஔΛऔಘ
  76. LFZJOIFSJUFEUZQFT< \ LFZOBNF'MPX(SBQI5ZQF ^ >  LFZLJOETPVSDFMBOHTXJGUEFDMDMBTT  LFZMFOHUI 

    LFZOBNF%PPS  LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU  LFZSVOUJNF@OBNF@5U$@@NBJO@@%PPS  LFZTVCTUSVDUVSF< \ LFZBDDFTTJCJMJUZTPVSDFMBOHTXJGUBDDFTTJCJM OBNFʹDMBTTͷ໊લ
  77. εςʔτΛ୳͢

  78. init() { let builder = FlowGraphBuilder<Door>() // ด͍ͯ͡Δ builder.add(waiting: .closed)

    { event in if case .open = event.kind { return .run(.opening, event) } else { return .stay } } // ։͍͍ͯΔ builder.add(waiting: .opened) { event in if case .close = event.kind { return .run(.closing, event) } else { return .stay
  79. \ LFZCPEZMFOHUI  LFZCPEZP⒎TFU  LFZLJOETPVSDFMBOHTXJGUFYQSDBMM  LFZMFOHUI  LFZOBNFCVJMEFSBEE

     LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZCPEZMFOHUI  LFZCPEZP⒎TFU  LFZLJOETPVSDFMBOHTXJGUFYQSBSHVNFOU  LFZMFOHUI  LFZOBNFXBJUJOH  LFZOBNFMFOHUI  FYQSDBMM͕ؔ਺ݺͼग़͠
  80. \ LFZCPEZMFOHUI  LFZCPEZP⒎TFU  LFZLJOETPVSDFMBOHTXJGUFYQSDBMM  LFZMFOHUI  LFZOBNFCVJMEFSBEE

     LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZCPEZMFOHUI  LFZCPEZP⒎TFU  LFZLJOETPVSDFMBOHTXJGUFYQSBSHVNFOU  LFZMFOHUI  LFZOBNFXBJUJOH  LFZOBNFMFOHUI  FYQSDBMMͷOBNFʹ ؔ਺໊
  81. LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZCPEZMFOHUI 

    LFZCPEZP⒎TFU  LFZLJOETPVSDFMBOHTXJGUFYQSBSHVNFOU  LFZMFOHUI  LFZOBNFXBJUJOH  LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU ^  \ LFZCPEZMFOHUI  LFZCPEZP⒎TFU  BSHVNFOU͕ ؔ਺ͷҾ਺
  82. LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZCPEZMFOHUI 

    LFZCPEZP⒎TFU  LFZLJOETPVSDFMBOHTXJGUFYQSBSHVNFOU  LFZMFOHUI  LFZOBNFXBJUJOH  LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU ^  \ LFZCPEZMFOHUI  LFZCPEZP⒎TFU  BSHVNFOUͷOBNFʹ Ҿ਺ͷϥϕϧ
  83. LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZCPEZMFOHUI 

    LFZCPEZP⒎TFU  LFZLJOETPVSDFMBOHTXJGUFYQSBSHVNFOU  LFZMFOHUI  LFZOBNFXBJUJOH  LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU ^  \ LFZCPEZMFOHUI  LFZCPEZP⒎TFU  Ҿ਺ͷ஋ͷ෦෼͸Ґஔ͚ͩ
  84. init() { let builder = FlowGraphBuilder<Door>() // ด͍ͯ͡Δ builder.add(waiting: .closed)

    { event in if case .open = event.kind { return .run(.opening, event) } else { return .stay } } // ։͍͍ͯΔ builder.add(waiting: .opened) { event in if case .close = event.kind { return .run(.closing, event) } else { return .stay SFUVSOͷҐஔ͸Θ͔Βͳ͍
  85. 4ZOUBY 4ZOUBY.BQ

  86. {type:comment offset:0, length:3, content:'// '}, {type:comment offset:3, length:15, content:'// Door.swift

    '}, {type:comment offset:18, length:3, content:'// '}, {type:keyword offset:22, length:6, content:'import'}, {type:identifier offset:29, length:9, content:'FlowGraph'}, {type:comment offset:40, length:19, content:'// υΞͷঢ়ଶ '}, {type:keyword offset:59, length:5, content:'class'}, {type:identifier offset:65, length:4, content:'Door'}, {type:typeidentifier offset:71, length:13, content:'FlowGraphType'}, {type:attributeBuiltin offset:91, length:12, content:'private(set)'}, {type:keyword offset:104, length:3, content:'var'}, {type:identifier offset:108, length:6, content:'isOpen'}, {type:typeidentifier offset:116, length:4, content:'Bool'}, {type:keyword offset:123, length:5, content:'false'}, {type:keyword offset:139, length:6, content:'didSet'}, {type:identifier offset:160, length:5, content:'print'}, {type:string offset:166, length:8, content:'"isOpen '}, {type:stringInterpolationAnchor offset:175, length:1, content:'('}, {type:keyword offset:176, length:4, content:'self'}, {type:identifier offset:181, length:6, content:'isOpen'}, {type:stringInterpolationAnchor offset:187, length:1, content:')'},
  87. {type:keyword offset:59, length:5, content:'class'}

  88. {type:identifier offset:65, length:4, content:'Door'}

  89. {type:comment offset:40, length:19, content:'// υΞͷঢ়ଶ '}

  90. init() { let builder = FlowGraphBuilder<Door>() // ด͍ͯ͡Δ builder.add(waiting: .closed)

    { event in if case .open = event.kind { return .run(.opening, event) } else { return .stay } } // ։͍͍ͯΔ builder.add(waiting: .opened) { event in if case .close = event.kind { return .run(.closing, event) } else { return .stay ؔ਺ͷCPEZ෦෼
  91. '}, {type:identifier offset:800, length:7, content:'builder'}, {type:identifier offset:808, length:3, content:'add'}, {type:identifier

    offset:812, length:7, content:'waiting'}, {type:identifier offset:822, length:6, content:'closed'}, {type:identifier offset:832, length:5, content:'event'}, {type:keyword offset:838, length:2, content:'in'}, {type:keyword offset:853, length:2, content:'if'}, {type:keyword offset:856, length:4, content:'case'}, {type:identifier offset:862, length:4, content:'open'}, {type:identifier offset:869, length:5, content:'event'}, {type:identifier offset:875, length:4, content:'kind'}, {type:keyword offset:898, length:6, content:'return'}, {type:identifier offset:906, length:3, content:'run'}, {type:identifier offset:911, length:7, content:'opening'}, {type:identifier offset:920, length:5, content:'event'}, {type:keyword offset:941, length:4, content:'else'}, {type:keyword offset:964, length:6, content:'return'}, {type:identifier offset:972, length:4, content:'stay'}, {type:comment offset:1018, length:19, content:'// ։͍͍ͯΔ '}, {type:identifier offset:1045, length:7, content:'builder'}, {type:identifier offset:1053, length:3, content:'add'}, {type:identifier offset:1057, length:7, content:'waiting'}, {type:identifier offset:1067, length:6, content:'opened'},
  92. '}, {type:identifier offset:800, length:7, content:'builder'}, {type:identifier offset:808, length:3, content:'add'}, {type:identifier

    offset:812, length:7, content:'waiting'}, {type:identifier offset:822, length:6, content:'closed'}, {type:identifier offset:832, length:5, content:'event'}, {type:keyword offset:838, length:2, content:'in'}, {type:keyword offset:853, length:2, content:'if'}, {type:keyword offset:856, length:4, content:'case'}, {type:identifier offset:862, length:4, content:'open'}, {type:identifier offset:869, length:5, content:'event'}, {type:identifier offset:875, length:4, content:'kind'}, {type:keyword offset:898, length:6, content:'return'}, {type:identifier offset:906, length:3, content:'run'}, {type:identifier offset:911, length:7, content:'opening'}, {type:identifier offset:920, length:5, content:'event'}, {type:keyword offset:941, length:4, content:'else'}, {type:keyword offset:964, length:6, content:'return'}, {type:identifier offset:972, length:4, content:'stay'}, {type:comment offset:1018, length:19, content:'// ։͍͍ͯΔ '}, {type:identifier offset:1045, length:7, content:'builder'}, {type:identifier offset:1053, length:3, content:'add'}, {type:identifier offset:1057, length:7, content:'waiting'}, {type:identifier offset:1067, length:6, content:'opened'},
  93. εςʔτͷ5PLFOΛղੳ͢Δ

  94. waiting closed event in if case open event kind return

    run opening event else return stay ಄͔Βॱ൪ʹݟ͍ͯ͘
  95. waiting closed event in if case open event kind return

    run opening event else return stay XBJUJOH͔ SVOOJOH ͳΒʜ XBJUJOH
  96. waiting closed event in if case open event kind return

    run opening event else return stay ࣍͸ εςʔτ໊ XBJUJOH DMPTFE
  97. waiting closed event in if case open event kind return

    run opening event else return stay JOͷޙ͔Β Ϋϩʔδϟ XBJUJOH DMPTFE
  98. waiting closed event in if case open event kind return

    run opening event else return stay SFUVSOΛ୳͢ XBJUJOH DMPTFE
  99. waiting closed event in if case open event kind return

    run opening event else return stay SVO͔ XBJUͳΒʜ XBJUJOH DMPTFE
  100. waiting closed event in if case open event kind return

    run opening event else return stay ਐΉઌͷ εςʔτ໊ XBJUJOH DMPTFE PQFOJOH
  101. waiting closed event in if case open event kind return

    run opening event else return stay SFUVSOΛ୳͢ XBJUJOH DMPTFE PQFOJOH
  102. waiting closed event in if case open event kind return

    run opening event else return stay TUBZͳΒແࢹ XBJUJOH DMPTFE PQFOJOH
  103. εςʔτղੳͷ ঢ়ଶભҠਤ

  104. %PU

  105. digraph { graph [label = "Door", labelloc = "t", labeljust

    = "l", fontcolor = "#333333", rankdir = "TB", fontname = "Osaka-Mono", fontsize = "12", charset = "UTF-8"] node [fontcolor = "#333333", fillcolor = "#F9F9F9", fontname = "Osaka-Mono", style = "solid,filled", fontsize = "10", color = "#CCCCCC"] edge [fontcolor = "#333333", fontname = "Osaka-Mono", fontsize = "9", color = "#AAAAAA"] opened [shape = "record", label = "{opened|։͍͍ͯΔ}", color = "#BBBBBB"] closing [shape = "record", label = "{closing|ด͡Δ}", color = "#40C5EE"] closed [shape = "record", label = "{closed|ด͍ͯ͡Δ}", color = "#00D54B"] opening [shape = "record", label = "{opening|։͘}", color = "#40C5EE"] "opened" -> "closing" [style = "solid", color = "#99DEF3"] "closing" -> "closed" [style = "dashed", color = "#AAAAAA"] "closed" -> "opening" [style = "solid", color = "#99DEF3"] "opening" -> "opened" [style = "dashed", color = "#AAAAAA"] } %PPSEPU
  106. digraph { graph [label = "Door", labelloc = "t fontcolor

    = "#333333", rankdi fontname = "Osaka-Mono", font charset = "UTF-8"] node [fontcolor = "#333333", fillcol fontname = "Osaka-Mono", style fontsize = "10", color = "#CCC edge [fontcolor = "#333333", fontnam fontsize = "9", color = "#AAAA opened [shape = "record", label = "{ EJHSBQI͸༗޲άϥϑ %PPSEPU
  107. charset = "UTF-8"] node [fontcolor = "#333333", fillcolor = "

    fontname = "Osaka-Mono", style = "so fontsize = "10", color = "#CCCCCC"] edge [fontcolor = "#333333", fontname = "O fontsize = "9", color = "#AAAAAA"] opened [shape = "record", label = "{opened|։͍͍ͯΔ}", color = "#BBBBBB"] closing [shape = "record", label = "{closi color = "#40C5EE"] closed [shape = "record", label = "{closed color = "#00D54B"] opening [shape = "record", label = "{openi color = "#40C5EE"] ϊʔυͷ໊લ ϊʔυ
  108. charset = "UTF-8"] node [fontcolor = "#333333", fillcolor = "

    fontname = "Osaka-Mono", style = "so fontsize = "10", color = "#CCCCCC"] edge [fontcolor = "#333333", fontname = "O fontsize = "9", color = "#AAAAAA"] opened [shape = "record", label = "{opened|։͍͍ͯΔ}", color = "#BBBBBB"] closing [shape = "record", label = "{closi color = "#40C5EE"] closed [shape = "record", label = "{closed color = "#00D54B"] opening [shape = "record", label = "{openi color = "#40C5EE"] <>ͷதʹදࣔ͞ΕΔத਎ ϊʔυ
  109. closing [shape = "record", label = "{closing color = "#40C5EE"]

    closed [shape = "record", label = "{closed|ด color = "#00D54B"] opening [shape = "record", label = "{opening color = "#40C5EE"] "opened" -> "closing" [style = "solid", color = "#99DEF3"] "closing" -> "closed" [style = "dashed", col "closed" -> "opening" [style = "solid", colo "opening" -> "opened" [style = "dashed", col } Τοδ ͰϊʔυΛͭͳ͛Δ
  110. 'MPX(SBQI IUUQTHJUIVCDPNPCKFDUJWFBVEJP4XJGU'MPX(SBQI 'MPX(SBQI%PU$POWFSUFS IUUQTHJUIVCDPNPCKFDUJWFBVEJP'MPX(SBQI%PU$POWFSUFS 4PVSDF,JUUFO (SBQIWJ[ IUUQTHJUIVCDPNKQTJN4PVSDF,JUUFO IUUQTXXXHSBQIWJ[PSH ຊ೔ͷαϯϓϧ IUUQTHJUIVCDPNPCKFDUJWFBVEJPJ04%$