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

iOSDC2018.pdf

Yuki Yasoshima
August 31, 2018
1.7k

 iOSDC2018.pdf

Yuki Yasoshima

August 31, 2018
Tweet

Transcript

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

    View full-size slide

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

    View full-size slide

  3. ྫɿυΞͷ։ด

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  16. "45
    IUUQTTQFBLFSEFDLDPNLJTIJLBXBLBUTVNJBTUNFUBQSPHSBNNJOHJOTXJGU
    AST meta-programming in Swift
    try! Swift Tokyo 2018
    Abstract Syntax Tree

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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
    init() {
    let builder = FlowGraphBuilder()
    // ด͍ͯ͡Δ
    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

    View full-size slide

  20. γΣϧεΫϦϓτͰ
    ΍͍ͬͯΔ͜ͱ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  26. 'MPX(SBQI%PPS
    DMPTFE PQFOFE
    &WFOU
    &WFOU
    ֎෦͔Β$VSSFOUͷ8BJUJOH4UBUFʹ౉͞ΕΔ
    8BUJOH4UBUF͔Β3VOOJOH4UBUFʹ౉͞ΕΔ
    $VSSFOU
    DMPTJOH

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  36. 'MPX(SBQIͷॻ͖ํ
    ܕͷఆٛ
    ઃܭΦϒδΣΫτͷੜ੒
    εςʔτͷొ࿥
    ࣮ߦΦϒδΣΫτͷੜ੒
    ΠϕϯτΛड͚औΔ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  41. 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
    }

    View full-size slide

  42. ઃܭΦϒδΣΫτͷੜ੒

    View full-size slide

  43. let builder = FlowGraphBuilder()
    'MPX(SBQI#VJMEFSΛੜ੒

    View full-size slide

  44. εςʔτͷొ࿥

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  54. builder.add(running: .opening) { event in
    event.object.isOpen = true
    return .wait(.opened)
    }
    ผͷεςʔτʹભҠ͢Δ
    3VOOJOH4UBUFͷొ࿥
    ❇3VOOJOH4UBUFʹཹ·Δ͜ͱ͸Ͱ͖ͳ͍

    View full-size slide

  55. ࣮ߦΦϒδΣΫτͷੜ੒

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  59. Πϕϯτͷड͚औΓ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  62. 'MPX(SBQI%PU$POWFSUFS

    View full-size slide

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

    View full-size slide

  64. w4USVDUVSF
    w4ZOUBY
    ղੳ͢Δػೳ

    View full-size slide

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

    View full-size slide

  66. \
    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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  69. LFZP⒎TFU
    LFZTVCTUSVDUVSF<
    \
    LFZBDDFTTJCJMJUZTPVSDFMBOHTXJGUBDDFTTJCJ
    LFZCPEZMFOHUI
    LFZCPEZP⒎TFU
    LFZFMFNFOUT<
    \
    LFZLJOETPVSDFMBOHTXJGUTUSVDUVSFFMFN
    LFZMFOHUI
    LFZP⒎TFU
    ^
    >
    LFZJOIFSJUFEUZQFT<
    LJOE͸ཁૉͷछྨ

    View full-size slide

  70. ΫϥεΛ୳͢

    View full-size slide

  71. // 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)?

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  74. LFZJOIFSJUFEUZQFT<
    \
    LFZOBNF'MPX(SBQI5ZQF
    ^
    >
    LFZLJOETPVSDFMBOHTXJGUEFDMDMBTT
    LFZMFOHUI
    LFZOBNF%PPS
    LFZOBNFMFOHUI
    LFZOBNFP⒎TFU
    LFZP⒎TFU
    LFZSVOUJNF@OBNF@5U$@@NBJO@@%PPS
    LFZTVCTUSVDUVSF<
    \
    LFZBDDFTTJCJMJUZTPVSDFMBOHTXJGUBDDFTTJCJM
    OBNFʹDMBTTͷ໊લ

    View full-size slide

  75. εςʔτΛ୳͢

    View full-size slide

  76. init() {
    let builder = FlowGraphBuilder()
    // ด͍ͯ͡Δ
    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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  81. LFZOBNFMFOHUI
    LFZOBNFP⒎TFU
    LFZP⒎TFU
    LFZTVCTUSVDUVSF<
    \
    LFZCPEZMFOHUI
    LFZCPEZP⒎TFU
    LFZLJOETPVSDFMBOHTXJGUFYQSBSHVNFOU
    LFZMFOHUI
    LFZOBNFXBJUJOH
    LFZOBNFMFOHUI
    LFZOBNFP⒎TFU
    LFZP⒎TFU
    ^
    \
    LFZCPEZMFOHUI
    LFZCPEZP⒎TFU
    Ҿ਺ͷ஋ͷ෦෼͸Ґஔ͚ͩ

    View full-size slide

  82. init() {
    let builder = FlowGraphBuilder()
    // ด͍ͯ͡Δ
    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ͷҐஔ͸Θ͔Βͳ͍

    View full-size slide

  83. 4ZOUBY 4ZOUBY.BQ

    View full-size slide

  84. {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:')'},

    View full-size slide

  85. {type:keyword
    offset:59,
    length:5,
    content:'class'}

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  88. init() {
    let builder = FlowGraphBuilder()
    // ด͍ͯ͡Δ
    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෦෼

    View full-size slide

  89. '},
    {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'},

    View full-size slide

  90. '},
    {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'},

    View full-size slide

  91. εςʔτͷ5PLFOΛղੳ͢Δ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  100. waiting
    closed
    event
    in
    if
    case
    open
    event
    kind
    return
    run
    opening
    event
    else
    return
    stay TUBZͳΒແࢹ
    XBJUJOH
    DMPTFE
    PQFOJOH

    View full-size slide

  101. εςʔτղੳͷ
    ঢ়ଶભҠਤ

    View full-size slide

  102. 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

    View full-size slide

  103. 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

    View full-size slide

  104. 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"]
    ϊʔυͷ໊લ
    ϊʔυ

    View full-size slide

  105. 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"]
    <>ͷதʹදࣔ͞ΕΔத਎
    ϊʔυ

    View full-size slide

  106. 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
    }
    Τοδ
    ͰϊʔυΛͭͳ͛Δ

    View full-size slide

  107. 'MPX(SBQI
    IUUQTHJUIVCDPNPCKFDUJWFBVEJP4XJGU'MPX(SBQI
    'MPX(SBQI%PU$POWFSUFS
    IUUQTHJUIVCDPNPCKFDUJWFBVEJP'MPX(SBQI%PU$POWFSUFS
    4PVSDF,JUUFO
    (SBQIWJ[
    IUUQTHJUIVCDPNKQTJN4PVSDF,JUUFO
    IUUQTXXXHSBQIWJ[PSH
    ຊ೔ͷαϯϓϧ
    IUUQTHJUIVCDPNPCKFDUJWFBVEJPJ04%$

    View full-size slide