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

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

Avatar for Yuta Koshizawa Yuta Koshizawa
September 16, 2017
6.9k

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

Avatar for Yuta Koshizawa

Yuta Koshizawa

September 16, 2017
Tweet

More Decks by Yuta Koshizawa

Transcript

  1. 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() }
  2. Javaͷ৔߹ Throwable -+- Exception -+- RuntimeException -+- NullPointerException | |

    +- IndexOutOfBoundsException | | ... | | | +- IOException | +- SQLException | ... | +- Error - ... -+- OutOfMemoryError +- StackOverflowError ...
  3. 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() }
  4. Universal error ͕ϋϯυϦϯάՄೳͩͬͨͱ͢Δͱ // ϝϞϦෆ଍ͷϋϯυϦϯάͷྫ let foo: Foo? = allocate(size(of:

    Foo)) guard let foo = foo else { // Τϥʔϝοηʔδͷੜ੒Ͱ͞ΒʹϝϞϦෆ଍͕ى͜Δ͔΋ showAlert("ϝϞϦ͕଍Γ·ͤΜɻ") }
  5. 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 } } } }
  6. 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 } } } }
  7. 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 } } } }
  8. 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 } } } }
  9. 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 } } } }
  10. ؔ਺ -Onone -O -Ounchecked fatalError ◦ ◦ ◦ precondi/on ◦

    ◦ assert ◦ ※ ◦͕෇͍͍ͯͳ͍૊Έ߹Θͤ͸νΣοΫ͕লུ͞ΕΔ
  11. 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 } } } }
  12. 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 } } } }
  13. precondition ͩͱ͏Ε͍͠ཧ༝ // guard ͱ fatalError ͰΠϯσοΫεͷνΣοΫ struct Array<Element> {

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

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

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

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

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

    let b: UInt8 = 255 print(b + 1) // ࣮ߦ࣌ΤϥʔʹͳΒͳ͍
  19. 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])
  20. // Simple domain error Ͱͳ͘ Recoverable Ͱ͋ͬͯ΄͍͠ let string =

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

    a = malloc(MemoryLayout<Int>.size * 100_000_000) else { showAlert("ϝϞϦ͕଍Γ·ͤΜɻ") return } // a Λ࢖͏ॲཧ
  22. 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
  23. // Ͳ͏ͤ ! ͢Δ͜ͱʹͳͬͯແବ 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 } } } }
  24. 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 } ... } ... }
  25. 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() } ... } ... }
  26. 3. Logic failure struct Board { subscript(x: Int, y: Int)

    -> Disk? { precondition((0..<8).contains(x)) precondition((0..<8).contains(y)) ... } ... }
  27. struct Board { subscript(x: Int, y: Int) -> Disk? {

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

    precondition((0..<8).contains(x)) precondition((0..<8).contains(y)) ... } ... }
  29. 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) }
  30. 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() } }
  31. 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) }
  32. 1. Recoverable error func readFoo() throws -> Foo { guard

    isFooSensorAvailable() else { throw ... } ... }
  33. 1. Recoverable error func loadGame() throws -> Game? { ...

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

    hash == savedHash else { fatalError() } ... }
  35. // ϥΠϒϥϦϨΠϠʔ func loadGame() -> Game? { ... } //

    ΞϓϦϨΠϠʔ func ... { guard let game = loadGame() else { fatalError() } // game Λ࢖͏ίʔυ }
  36. 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 } ... } }
  37. 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() } ... } }
  38. 3. Logic failure struct Image<Pixel> { init(width: Int, height: Int,

    pixels: [Pixel]) { precondition(width >= 0) precondition(height >= 0) precondition(pixels.count == width) ... } }