Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

先取り! Swift 6 の async/await

先取り! Swift 6 の async/await

Swift の async/await の Proposal が Accept されました。これによって、 Swift に async/await が導入されることが決定しました。おそらく、 Swift 6 で導入されるものと思われます。

本スライドは https://www.youtube.com/watch?v=OZN_YFZy770&t=1467 の動画と合わせて御覧下さい。 Swift の async/await の解説と練習問題を実施しています。練習問題は、実務で async/await を使うことになりそうなケースを取り上げています。

また、練習問題と解答例のソースコードは https://github.com/koher/async-await-challenge からもご覧いただけます。

Yuta Koshizawa

January 23, 2021
Tweet

More Decks by Yuta Koshizawa

Other Decks in Programming

Transcript

  1. Swi$ ͷඇಉظॲཧʢ͜Ε·Ͱʣ func download(from url: URL, completion: @escaping (Data) ->

    Void) download(from: url) { data in // ͜͜Ͱඇಉظʹड͚औͬͨ data Λ࢖͏ }
  2. Swi$ ͷඇಉظॲཧʢ͜Ε͔Βʣ func download(from url: URL) async -> Data let

    data = await download(from: url) // ͜͜Ͱඇಉظʹड͚औͬͨ data Λ࢖͏
  3. Poten&al Suspension Point func download(from url: URL) async -> Data

    func downloadImage(from url: URL) async -> UIImage { // Potential Suspension Point let data = await download(from: url) // (A) let image = UIImage(data: data)! // (B) return image }
  4. RPG ͷྫͱϒϩοΩϯά func performTurn(of character: Character) { ... switch action

    { ... case .spell: // (1) ຐ๏Λબ୒ let spell = selectSpell(of: character) // (2) ຐ๏Λ͔͚Δ૬खΛબ୒ let target = selectTarget(of: spell) // (3) ຐ๏Λ࣮ߦ perform(spell, on: target) } }
  5. RPG ͷྫͱϒϩοΩϯά func performTurn(of character: Character) async { ... switch

    action { ... case .spell: // (1) ຐ๏Λબ୒ let spell = await selectSpell(of: character) // (2) ຐ๏Λ͔͚Δ૬खΛબ୒ let target = await selectTarget(of: spell) // (3) ຐ๏Λ࣮ߦ await perform(spell, on: target) } }
  6. ίʔϧόοΫ஍ࠈ foo { a in bar(a) { b in baz(b)

    { c in qux(c) { d in self.x = d } } } }
  7. async/await ͳΒ let a = await foo() let b =

    await bar(a) let c = await baz(b) let d = await qux(c) self.x = d
  8. Future ͩͱ foo().flatMap { a in bar(a) }.flatMap { b

    in baz(b) }.flatMap { c in qux(c) }.sink { d in self.x = d }.store(in: &cancellables)
  9. ੍ޚߏ଄ͱͷ૊Έ߹Θͤ let x = await foo() var sum = 0

    while x > 0 { sum += x x = await bar(x) if x.isMultiple(of: 2) { return nil } } return sum
  10. Τϥʔ͕ى͜ΓಘΔ৔߹ʢίʔϧόοΫʣ func download(from url: URL, completion: @escaping (Result<Data, Error>) ->

    Void) download(from: url) { result in do { let data: Data = try result.get() // ͜͜Ͱ data Λ࢖͏ } catch { // ͜͜ͰΤϥʔॲཧΛߦ͏ } }
  11. Τϥʔ͕ى͜ΓಘΔ৔߹ʢ async/await ʣ func download(from url: URL) async throws ->

    Data do { let data = try await download(from: url) // ͜͜Ͱ data Λ࢖͏ } catch { // ͜͜ͰΤϥʔॲཧΛߦ͏ }
  12. ฒߦॲཧʢ JS ʣʁ const a = await foo(); // number

    const b = await bar(); // number console.log(a + b);
  13. ฒߦॲཧʢ JS ʣ const a = foo(); // Promise<number> const

    b = bar(); // Promise<number> console.log(await a + await b);
  14. ฒߦॲཧʢ Swi% ʣ async let a = foo() // Int

    async let b = bar() // Int print(await a + b)
  15. inout func foo(_ x: inout Int) -> () -> Int

    { let bar: () -> Int = { return x + 1 } // return bar } var a = 42 let bar = foo(&a) a += 1 print(bar())
  16. Structured concurrency5 The concept was formulated in 2016 by Mar7n

    Sústrik ..., and then further refined in 2018 by Nathaniel J. Smith, ... Meanwhile, Roman Elizarov independently came upon the same ideas while developing an experimental corou7ne library for the Kotlin language. In 2019, the loom project from OpenJDK is adop8ng structured concurrency ... In 2020, Swi? is men8oning adop8on of structured concurrency in their concurrency roadmap. 5 h$ps:/ /en.wikipedia.org/wiki/Structured_concurrency
  17. async // @asyncHandler func bar() async { print(2) await foo1()

    print(3) await foo2() print(4) } print(1) await bar() print(5)
  18. Task.runDetached func foo() async {} func bar() { let handle

    = Task.runDetached { await foo() } handle.cancel() }
  19. Task func foo() async { // Thread A await bar()

    // Thread B await baz() // Threac C }
  20. Task func foo() async { // Task A await bar()

    // Task A await baz() // Task A }
  21. Child Task func foo() async -> Int { // Task

    A async let a = bar() // Task A async let b = baz() // Task A return await a + b }
  22. Child Task func bar() async -> Int { // Task

    A' ... } func bar() async -> Int { // Task A'' ... }
  23. Child Task func foo() async -> Int { // Task

    A async let a = bar() // Task A async let b = baz() // Task A return await a + b }
  24. Task Tree શମͷΩϟϯηϧ func foo() async { // ෳࡶͳ Task

    Tree Λ࣋ͭඇಉظॲཧ } func bar() { let handle = Task.runDetached { await foo() } handle.cancel() }
  25. ίʔϧόοΫ → async func foo(completion: @escaping (Int) -> Void) {

    ... } func foo() async -> Int { // ίʔϧόοΫ൛ͷ foo Λ࢖ͬͯͲ͏΍࣮ͬͯ૷͢Δʁ }
  26. ίʔϧόοΫ → async ʢ JS ʣ function fooCallback(completion) { ...

    } function fooAsync() { return new Promise((resolve) => { fooCallback(value => { resolve(value); }); }); }
  27. ίʔϧόοΫ → async ʢ Swi& ʣ func foo(completion: @escaping (Int)

    -> Void) { ... } func foo() async -> Int { await withUnsafeContinuation { continuation in foo { value in continuation.resume(returning: value) } } }
  28. SE-0300: Con+nua+ons for interfacing async tasks with synchronous code7 7

    h$ps:/ /github.com/apple/swi6-evolu9on/blob/main/proposals/0300-con9nua9on.md