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

具体例とクイズで学ぶ、Swiftの4種類のエラーの使い分け

3c031541ed3d92869414857dfef853de?s=47 Yuta Koshizawa
September 16, 2017
5.3k

 具体例とクイズで学ぶ、Swiftの4種類のエラーの使い分け

3c031541ed3d92869414857dfef853de?s=128

Yuta Koshizawa

September 16, 2017
Tweet

Transcript

  1. ۩ମྫͱΫΠζͰֶͿɺ Swi$ͷ4छྨͷΤϥʔͷ࢖͍෼͚ Yuta Koshizawa @koher

  2. None
  3. None
  4. None
  5. None
  6. None
  7. Q. Swi' ͰΤϥʔΛදͦ͏ͱࢥͬͨ ͱ͖ʹԿΛ࢖͍·͔͢ʁ

  8. throw FooError()

  9. let number: Int? = Int(string)

  10. let foo: Foo? = try? foo()

  11. fatalError()

  12. assert(...)

  13. precondition(...)

  14. assertionFailure()

  15. preconditionFailure()

  16. fooOrNil!

  17. array[-1]

  18. Int.max + 1

  19. [Int](repeating: 42, count: Int.max)

  20. func foo() { foo() }

  21. throw FooError() let number: Int? = Int(String) let foo: Foo?

    = try? foo() fatalError() assert(...) assertionFailure() precondition(...) preconditionFailure() fooOrNil! array[-1] Int.max + 1 [Int](repeating: 42, count: Int.max) func foo() { foo() }
  22. Javaͷ৔߹ Throwable -+- Exception -+- RuntimeException -+- NullPointerException | |

    +- IndexOutOfBoundsException | | ... | | | +- IOException | +- SQLException | ... | +- Error - ... -+- OutOfMemoryError +- StackOverflowError ...
  23. throw FooError() let number: Int? = Int(string) let foo: Foo?

    = try? foo() fatalError() assert(...) assertionFailure() precondition(...) preconditionFailure() fooOrNil! array[-1] Int.max + 1 [Int](repeating: 42, count: Int.max) func foo() { foo() }
  24. None
  25. None
  26. None
  27. None
  28. None
  29. Simple domain errors Recoverable errors Universal errors Logic failures

  30. Simple domain errors

  31. let number: Int? = Int(string)

  32. Simple domain errors • ΦϖϨʔγϣϯ͕ࣦഊ͢Δલఏ৚͕݅໌֬ • ੒ޭ͔ࣦͨ͠ഊ͔͕ͨ͠෼͔Ε͹े෼ • Swi% Ͱ͸

    Optional Λฦ͢͜ͱͰද͢
  33. let element: Int? = array.first

  34. let value = dictionary["unknownKey"]

  35. Recoverable errors

  36. try fileManager .removeItem(at: url)

  37. Recoverable errors • ༷ʑͳݪҼͰΦϖϨʔγϣϯ͕ࣦഊ͢Δ • ࣦഊͷݪҼΛ஌Γ͍ͨ • ݪҼผʹϋϯυϦϯά͍ͨ͠ • Swi%

    Ͱ͸ Error Λ throw ͢Δ͜ͱͰද͢
  38. ճ෮ՄೳͳΤϥʔ Simple domain errors Recoverable errors

  39. ճ෮ෆೳͳΤϥʔ Universal errors Logic failures

  40. Universal errors

  41. [Int](repeating: 42, count: Int.max)

  42. Universal error ͕ϋϯυϦϯάՄೳͩͬͨͱ͢Δͱ // ϝϞϦෆ଍ͷϋϯυϦϯάͷྫ let foo: Foo? = allocate(size(of:

    Foo)) guard let foo = foo else { // Τϥʔϝοηʔδͷੜ੒Ͱ͞ΒʹϝϞϦෆ଍͕ى͜Δ͔΋ showAlert("ϝϞϦ͕଍Γ·ͤΜɻ") }
  43. func foo() { foo() }

  44. Ctrl + C

  45. thread.cancel()

  46. Universal errors • ίʔυதͷࢸΔͱ͜ΖͰൃੜ͢Δ΋ͷ͕ଟ͍ • ϋϯυϦϯά͠Α͏͕ͳ͍ • ίʔυ͔Βൃੜͤ͞Δʹ͸ NSException ʢ·ͨ͸

    fatalError ʣ
  47. Logic failures

  48. fooOrNil!

  49. Int.max + 1

  50. array[-1]

  51. Array ͷ subscript ͷࣦഊ͕ Logic failure ͳཧ༝ // [Int] Λιʔτ͢Δؔ਺

    func sort(_ ns: inout [Int]) { for i in 0 ..< ns.count { for j in i + 1 ..< ns.count { if ns[j] < ns[i] { let t = ns[j] ns[j] = ns[i] ns[i] = t } } } }
  52. Array ͷ subscript ͷࣦഊ͕ Logic failure ͳཧ༝ // [Int] Λιʔτ͢Δؔ਺

    func sort(_ ns: inout [Int]) { for i in 0 ..< ns.count { for j in i + 1 ..< ns.count { if ns[j] < ns[i] { let t = ns[j] ns[j] = ns[i] ns[i] = t } } } }
  53. Array ͷ subscript ͷࣦഊ͕ Logic failure ͳཧ༝ // ..< Λ

    ... ʹͯ͠͠·͏ͱΠϯσοΫε͕͸Έग़ͯΤϥʔ func sort(_ ns: inout [Int]) { for i in 0 ... ns.count { for j in i + 1 ... ns.count { if ns[j] < ns[i] { let t = ns[j] ns[j] = ns[i] ns[i] = t } } } }
  54. Array ͷ subscript ͷࣦഊ͕ Logic failure ͳཧ༝ // Ͱ΋ɺ͜͜Ͱ nil

    ͕ฦ͖ͬͯͯ΋ϋϯυϦϯά͠Α͏͕ͳ͍ func sort(_ ns: inout [Int]) { for i in 0 ... ns.count { for j in i + 1 ... ns.count { if ns[j] < ns[i] { let t = ns[j] ns[j] = ns[i] ns[i] = t } } } }
  55. Array ͷ subscript ͷࣦഊ͕ Logic failure ͳཧ༝ // Ͳ͏ͤ !

    ͢Δ͜ͱʹͳͬͯແବ func sort(_ ns: inout [Int]) { for i in 0 ... ns.count { for j in i + 1 ... ns.count { if ns[j]! < ns[i]! { let t = ns[j]! ns[j] = ns[i]! ns[i] = t } } } }
  56. Logic failures • ίʔυͷϛεʹΑͬͯൃੜ • ࣮ߦ࣌Ͱ͸ͳ͘ίʔυͷमਖ਼ʹΑͬͯରԠ • precondition, assert ͳͲͰൃੜͤ͞Δ

  57. ؔ਺ -Onone -O -Ounchecked fatalError ◦ ◦ ◦ precondi/on ◦

    ◦ assert ◦ ※ ◦͕෇͍͍ͯͳ͍૊Έ߹Θͤ͸νΣοΫ͕লུ͞ΕΔ
  58. precondition ͩͱ͏Ε͍͠ཧ༝ // [Int] Λιʔτ͢Δؔ਺ func sort(_ ns: inout [Int])

    { for i in 0 ..< ns.count { for j in i + 1 ..< ns.count { if ns[j] < ns[i] { let t = ns[j] ns[j] = ns[i] ns[i] = t } } } }
  59. precondition ͩͱ͏Ε͍͠ཧ༝ // [Int] Λιʔτ͢Δؔ਺ func sort(_ ns: inout [Int])

    { for i in 0 ..< ns.count { for j in i + 1 ..< ns.count { if ns[j] < ns[i] { let t = ns[j] ns[j] = ns[i] ns[i] = t } } } }
  60. precondition ͩͱ͏Ε͍͠ཧ༝ // guard ͱ fatalError ͰΠϯσοΫεͷνΣοΫ struct Array<Element> {

    subscript(index: Int): Element { get { guard 0 <= index && index < count else { fatalError() } ... } set { ... } } }
  61. precondition ͩͱ͏Ε͍͠ཧ༝ // guard ͱ fatalError ͰΠϯσοΫεͷνΣοΫ struct Array<Element> {

    subscript(index: Int): Element { get { guard 0 <= index && index < count else { fatalError() } ... } set { ... } } }
  62. precondition ͩͱ͏Ε͍͠ཧ༝ // precondition ͸ -Ounchecked ͰऔΓআ͔ΕΔ struct Array<Element> {

    subscript(index: Int): Element { get { precondition(0 <= index && index < count) ... } set { ... } } }
  63. -Onone ͷͱ͖ͷڍಈ // arrayindex.swift let a = [2, 3, 5]

    print(a[3]) $ swift arrayindex.swift fatal error: Index out of range
  64. -Ounchecked ͷͱ͖ͷڍಈ // arrayindex.swift let a = [2, 3, 5]

    print(a[3]) $ swift -Ounchecked arrayindex.swift 2392130230941712
  65. -Ounchecked ͷͱ͖ͷڍಈ let a: Int? = nil print(a!) // ࣮ߦ࣌ΤϥʔʹͳΒͳ͍

    let b: UInt8 = 255 print(b + 1) // ࣮ߦ࣌ΤϥʔʹͳΒͳ͍
  66. Logic failure ͸ίʔυͷϛεͷΑͬ ͯҾ͖ى͜͞ΕΔ ↕ ίʔυͷϛε͕ͳ͚Ε͹ Logic failure ͸ى͜Βͳ͍

  67. assert ͷ࢖༻ྫ assert ͸಺෦తͳ੔߹ੑͷνΣοΫʹ࢖͏ import TensorSwift // 10000 ਓ෼ͷ྆खͷࢦͷ௕͞ let

    tensor = Tensor(shape: [10000, 2, 5], elements: ...) // [ਓ, ࠨӈ, ࢦ] ͔Β [ࢦ, ਓ, ࠨӈ] ʹม׵ let transposed = tensor.transposed([2, 0, 1]) // ࠨखͷσʔλ͚ͩΛऔΓग़͢ let lefthand = tensor[..., ..., 1] // [ࢦ, ਓ] ͷॱʹͳ͍ͬͯͯ΄͍͚͠Ͳॲཧ͕ෳࡶͰࣗ৴͕࣋ͯͳ͍ͷͰνΣοΫ assert(lefthand.shape == [5, 10000])
  68. Simple domain errors Recoverable errors Universal errors Logic failures

  69. ΤϥʔͷछྨͷܾΊํ ͲΜͳ಺༰ͷΤϥʔ͔ ͲͷΑ͏ʹΤϥʔϋϯυϦϯά͍͔ͤͨ͞

  70. // Simple domain error Ͱͳ͘ Recoverable Ͱ͋ͬͯ΄͍͠ let string =

    "99999999999999999999999999" ... do { let number: Int = try Int(string) } catch is OverflowError { showAlert("\(Int.min) - \(Int.max) ͷ஋Λೖྗͯ͠Լ͍͞ɻ") } catch { showAlert("੔਺Λೖྗͯ͠Լ͍͞ɻ") }
  71. // Universal error Ͱ͸ͳ͘ Simple domain error Ͱ͋ͬͯ΄͍͠ guard let

    a = malloc(MemoryLayout<Int>.size * 100_000_000) else { showAlert("ϝϞϦ͕଍Γ·ͤΜɻ") return } // a Λ࢖͏ॲཧ
  72. // Simple domain error → Logic failure let number: Int

    = Int(string)!
  73. from \ to SDE RE UE LF SDE - guard

    let throw guard let fatalError ! RE try? - do-catch fatalError try! UE - LF if/guard return nil if/guard throw if/guard fatalError - SDE: Simple domain error, RE: Recoverable error, UE: Universal error, LF: Logic failure
  74. // Ͳ͏ͤ ! ͢Δ͜ͱʹͳͬͯແବ func sort(_ ns: inout [Int]) {

    for i in 0 ... ns.count { for j in i + 1 ... ns.count { if ns[j]! < ns[i]! { let t = ns[j]! ns[j] = ns[i]! ns[i] = t } } } }
  75. ΫΠζλΠϜ

  76. ΫΠζͷϧʔϧ - ࡾ୒ܗࣜ - ੍ݶ࣌ؒ͸ 30 ඵ - શ෦Ͱ 5

    ໰ - ඞͣࡾ୒ͷͲΕ͔ʹखΛڍ͛Δ
  77. ΫΠζͷϧʔϧ - ࡾ୒ܗࣜ - ੍ݶ࣌ؒ͸ 30 ඵ - શ෦Ͱ 5

    ໰ - ඞͣࡾ୒ͷͲΕ͔ʹखΛڍ͛Δ
  78. ΫΠζͷϧʔϧ - ࡾ୒ܗࣜ - ੍ݶ࣌ؒ͸ 30 ඵ - શ෦Ͱ 5

    ໰ - ඞͣࡾ୒ͷͲΕ͔ʹखΛڍ͛Δ
  79. ΫΠζͷϧʔϧ - ࡾ୒ܗࣜ - ੍ݶ࣌ؒ͸ 30 ඵ - શ෦Ͱ 5

    ໰ - ඞͣࡾ୒ͷͲΕ͔ʹखΛڍ͛Δ
  80. @koher h"ps:/ /twi"er.com/koher

  81. Q1. ϦόʔγͷϘʔυ

  82. let disk: Disk? = board[x, y]

  83. 1. Simple domain error struct Board { subscript(x: Int, y:

    Int) -> Disk? { guard (0..<8).contains(x) else { return nil } guard (0..<8).contains(y) else { return nil } ... } ... }
  84. 2. Universal error struct Board { subscript(x: Int, y: Int)

    -> Disk? { guard (0..<8).contains(x) else { fatalError() } guard (0..<8).contains(y) else { fatalError() } ... } ... }
  85. 3. Logic failure struct Board { subscript(x: Int, y: Int)

    -> Disk? { precondition((0..<8).contains(x)) precondition((0..<8).contains(y)) ... } ... }
  86. γϯΩϯάλΠϜ 1. Simple domain error 2. Universal error 3. Logic

    failure
  87. ౴͑ 1. Simple domain error 2. Universal error 3. Logic

    failure
  88. | ◦◦◦•|

  89. | •◦◦◦•|

  90. | ◦◦◦ |

  91. | •◦◦◦ |

  92. | ◦◦◦|

  93. | •◦◦◦|

  94. struct Board { subscript(x: Int, y: Int) -> Disk? {

    guard (0..<8).contains(x) else { return nil } guard (0..<8).contains(y) else { return nil } ... } ... }
  95. struct Board { subscript(x: Int, y: Int) -> Disk? {

    precondition((0..<8).contains(x)) precondition((0..<8).contains(y)) ... } ... }
  96. Q2. ΞϓϦʹόϯυϧ͞Εͨσʔλ

  97. let foo: Foo = loadFoo()

  98. 1. Recoverable error func loadFoo() throws -> Foo { guard

    let path = Bundle.main.path(forResource: "Foo", ofType: "json") else { throw ... } let url = URL(fileURLWithPath: path) let data = try Data(contentsOf: url) return try JSONDecoder().decode(Foo.self, from: data) }
  99. 2. Universal error func loadFoo() -> Foo { guard let

    path = Bundle.main.path(forResource: "Foo", ofType: "json") else { fatalError() } let url = URL(fileURLWithPath: path) do { let data = try Data(contentsOf: url) return try JSONDecoder().decode(Foo.self, from: data) } catch { fatalError() } }
  100. 3. Logic failure func loadFoo() -> Foo { let path

    = Bundle.main.path(forResource: "Foo", ofType: "json")! let url = URL(fileURLWithPath: path) let data = try! Data(contentsOf: url) return try! JSONDecoder().decode(Foo.self, from: data) }
  101. γϯΩϯάλΠϜ 1. Recoverable error 2. Universal error 3. Logic failure

  102. ౴͑ 1. Recoverable error 2. Universal error 3. Logic failure

  103. guard let image = UIImage(named: "Foo") else { // ΤϥʔϋϯυϦϯά

    ... } // image Λ࢖͏ॲཧ
  104. let image = UIImage(named: "Foo")! // image Λ࢖͏ॲཧ

  105. Q3. ηϯαʔ͔Βͷσʔλऔಘ

  106. let foo: Foo = readFoo()

  107. 1. Recoverable error func readFoo() throws -> Foo { guard

    isFooSensorAvailable() else { throw ... } ... }
  108. 2. Universal error func readFoo() -> Foo { guard isFooSensorAvailable()

    else { fatalError() } ... }
  109. 3. Logic failure func readFoo() -> Foo { precondition(isFooSensorAvailable()) ...

    }
  110. γϯΩϯάλΠϜ 1. Recoverable error 2. Universal error 3. Logic failure

  111. ౴͑ 1. Recoverable error 2. Universal error 3. Logic failure

  112. Q4. ήʔϜͷηʔϒσʔλ

  113. let game: Game? = loadGame()

  114. 1. Recoverable error func loadGame() throws -> Game? { ...

    guard hash == savedHash else { throw ... } ... }
  115. 2. Universal error func loadGame() -> Game? { ... guard

    hash == savedHash else { fatalError() } ... }
  116. 3. Logic failure func loadGame() -> Game? { ... precondition(hash

    == savedHash) ... }
  117. γϯΩϯάλΠϜ 1. Recoverable error 2. Universal error 3. Logic failure

  118. ౴͑ 1. Recoverable error 2. Universal error 3. Logic failure

  119. ౴͑ 1. Recoverable error 2. Universal error 3. Logic failure

  120. None
  121. // ϥΠϒϥϦϨΠϠʔ func loadGame() -> Game? { ... } //

    ΞϓϦϨΠϠʔ func ... { guard let game = loadGame() else { fatalError() } // game Λ࢖͏ίʔυ }
  122. Q5. ը૾ͷੜ੒

  123. let image = Image( width: width, height: height, pixels: pixels)

  124. 1. Simple domain error struct Image<Pixel> { init?(width: Int, height:

    Int, pixels: [Pixel]) { guard width >= 0 else { return nil } guard height >= 0 else { return nil } guard pixels.count == width * height else { return nil } ... } }
  125. 2. Universal error struct Image<Pixel> { init(width: Int, height: Int,

    pixels: [Pixel]) { guard width >= 0 else { return fatalError() } guard height >= 0 else { return fatalError() } guard pixels.count == width * height else { return fatalError() } ... } }
  126. 3. Logic failure struct Image<Pixel> { init(width: Int, height: Int,

    pixels: [Pixel]) { precondition(width >= 0) precondition(height >= 0) precondition(pixels.count == width) ... } }
  127. γϯΩϯάλΠϜ 1. Simple domain error 2. Universal error 3. Logic

    failure
  128. ౴͑ 1. Simple domain error 2. Universal error 3. Logic

    failure
  129. ౴͑ 1. Simple domain error 2. Universal error 3. Logic

    failure
  130. let a = [2, 3, 5] a.prefix(-1) // Logic failure

  131. print(3...2) // Logic failure