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

先取り! 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 からもご覧いただけます。

3c031541ed3d92869414857dfef853de?s=128

Yuta Koshizawa

January 23, 2021
Tweet

Transcript

  1. ઌऔΓʂSwi$ 6 ͷ async/await Yuta Koshizawa @koher

  2. SE-0296: Async/await4 4 h$ps:/ /github.com/apple/swi6-evolu9on/blob/main/proposals/0296-async-await.md

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

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

    data = await download(from: url) // ͜͜Ͱඇಉظʹड͚औͬͨ data Λ࢖͏
  5. throws/try func foo() throws {} func bar() { try foo()

    // ⛔ }
  6. throws/try func foo() throws {} func bar() throws { try

    foo() // ✅ }
  7. async/await func foo() async {} func bar() { await foo()

    // ⛔ }
  8. async/await func foo() async {} func bar() async { await

    foo() // ✅ }
  9. 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 }
  10. RPG ͷྫͱϒϩοΩϯά

  11. 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) } }
  12. 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) } }
  13. ίʔϧόοΫ஍ࠈ foo { a in bar(a) { b in baz(b)

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

    await bar(a) let c = await baz(b) let d = await qux(c) self.x = d
  15. 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)
  16. ੍ޚߏ଄ͱͷ૊Έ߹Θͤ 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
  17. ࿅श໰୊

  18. ໰୊ 01A h"ps:/ /swi)fiddle.com/m7nn4xoim62xdk7p5htbxmmau ໰୊ 01B h"ps:/ /swi)fiddle.com/zvnt3mp5tvgbbkd5mq5n3fvynm

  19. Τϥʔ͕ى͜ΓಘΔ৔߹ʢίʔϧόοΫʣ 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 { // ͜͜ͰΤϥʔॲཧΛߦ͏ } }
  20. Τϥʔ͕ى͜ΓಘΔ৔߹ʢ async/await ʣ func download(from url: URL) async throws ->

    Data do { let data = try await download(from: url) // ͜͜Ͱ data Λ࢖͏ } catch { // ͜͜ͰΤϥʔॲཧΛߦ͏ }
  21. ໰୊ 02A h"ps:/ /swi)fiddle.com/g7gvhfdug5hurbre2nzhifshaa ໰୊ 02B h"ps:/ /swi)fiddle.com/2si365hypvbd7pw27mp7hhibkm

  22. ໰୊ 03A h"ps:/ /swi)fiddle.com/5wnkjwkrzvhptlvhy7iukkfue4 ໰୊ 03B h"ps:/ /swi)fiddle.com/nbdwkt4yjzb23b33236wr5oj?

  23. ฒߦॲཧʁ let a = await foo() let b = await

    bar() print(a + b)
  24. ฒߦॲཧ async let a = foo() async let b =

    bar() print(await a + b)
  25. ฒߦॲཧʢ JS ʣʁ const a = await foo(); // number

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

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

    async let b = bar() // Int print(await a + b)
  28. 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())
  29. 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
  30. SE-NNNN: Structured concurrency6 6 h$ps:/ /github.com/DougGregor/swi7-evolu;on/blob/structured-concurrency/proposals/nnnn-structured- concurrency.md

  31. ໰୊ 04 h"ps:/ /swi)fiddle.com/dgvmmmc4fax8yu6474p37ke

  32. async ͷࠜͬ͜ func foo() async {} func bar() { await

    foo() // ⛔ }
  33. async ͷࠜͬ͜ • τοϓϨϕϧ • @main • @asyncHandler • Task.runDetached

    • ( runAsyncAndBlock )
  34. τοϓϨϕϧ await foo() await bar() await baz()

  35. runAsyncAndBlock runAsyncAndBlock { await foo() await bar() await baz() }

  36. @asyncHandler func foo() async {} @asyncHandler func bar() { await

    foo() }
  37. @asyncHandler @asyncHandler func bar() { print(2) await foo1() print(4) await

    foo2() print(5) } print(1) bar() print(3)
  38. async // @asyncHandler func bar() async { print(2) await foo1()

    print(3) await foo2() print(4) } print(1) await bar() print(5)
  39. ໰୊ 05 h"ps:/ /swi)fiddle.com/rhtpvch3rreovbcgw757c3keem

  40. @asyncHandler func foo() async {} @asyncHandler func bar() { await

    foo() }
  41. Task.runDetached func foo() async {} func bar() { Task.runDetached {

    await foo() } }
  42. Task.runDetached func foo() async {} func bar() { let handle

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

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

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

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

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

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

    Tree Λ࣋ͭඇಉظॲཧ } func bar() { let handle = Task.runDetached { await foo() } handle.cancel() }
  49. ໰୊ 06 h"ps:/ /swi)fiddle.com/mwjiy2f768ztaagrfrqs6lxhy

  50. ίʔϧόοΫ → async func foo(completion: @escaping (Int) -> Void) {

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

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

    -> Void) { ... } func foo() async -> Int { await withUnsafeContinuation { continuation in foo { value in continuation.resume(returning: value) } } }
  53. 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
  54. Con$nua$on • UnsafeContinuation • UnsafeThrowingContinuation • CheckedContinuation • CheckedThrowingContinuation

  55. UnsafeContinuation withUnsafeContinuation Ͱड͚औΔɻ struct UnsafeContinuation<T> { func resume(returning: T) }

  56. UnsafeThrowingContinuation withUnsafeThrowingContinuation Ͱड͚औΔɻ struct UnsafeThrowingContinuation<T> { func resume(returning: T) func

    resume(throwing: Error) func resume<E: Error>(with result: Result<T, E>) }
  57. ໰୊ 07 h"ps:/ /swi)fiddle.com/tuu5w2k37jdu5:k6gv5>hcni

  58. ·ͱΊ • async/await (Accepted) • async let • @asyncHandler •

    Task.Handle • Con&nua&on (Ac)ve review)