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

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

Yuta Koshizawa
September 16, 2017
6.4k

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

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