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

Yuta Koshizawa

January 23, 2021
Tweet

More Decks by Yuta Koshizawa

Other Decks in Programming

Transcript

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

    View Slide

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

    View Slide

  3. Swi$ ͷඇಉظॲཧʢ͜Ε·Ͱʣ
    func download(from url: URL,
    completion: @escaping (Data) -> Void)
    download(from: url) { data in
    // ͜͜Ͱඇಉظʹड͚औͬͨ data Λ࢖͏
    }

    View Slide

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

    View Slide

  5. throws/try
    func foo() throws {}
    func bar() {
    try foo() //

    }

    View Slide

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

    }

    View Slide

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

    }

    View Slide

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

    }

    View Slide

  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
    }

    View Slide

  10. RPG ͷྫͱϒϩοΩϯά

    View Slide

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

    View Slide

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

    View Slide

  13. ίʔϧόοΫ஍ࠈ
    foo { a in
    bar(a) { b in
    baz(b) { c in
    qux(c) { d in
    self.x = d
    }
    }
    }
    }

    View Slide

  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

    View Slide

  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)

    View Slide

  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

    View Slide

  17. ࿅श໰୊

    View Slide

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

    View Slide

  19. Τϥʔ͕ى͜ΓಘΔ৔߹ʢίʔϧόοΫʣ
    func download(from url: URL,
    completion: @escaping (Result) -> Void)
    download(from: url) { result in
    do {
    let data: Data = try result.get()
    // ͜͜Ͱ data Λ࢖͏
    } catch {
    // ͜͜ͰΤϥʔॲཧΛߦ͏
    }
    }

    View Slide

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

    View Slide

  21. ໰୊ 02A
    h"ps:/
    /swi)fiddle.com/g7gvhfdug5hurbre2nzhifshaa
    ໰୊ 02B
    h"ps:/
    /swi)fiddle.com/2si365hypvbd7pw27mp7hhibkm

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  27. ฒߦॲཧʢ Swi% ʣ
    async let a = foo() // Int
    async let b = bar() // Int
    print(await a + b)

    View Slide

  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())

    View Slide

  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

    View Slide

  30. SE-NNNN: Structured concurrency6
    6 h$ps:/
    /github.com/DougGregor/swi7-evolu;on/blob/structured-concurrency/proposals/nnnn-structured-
    concurrency.md

    View Slide

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

    View Slide

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

    }

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  37. @asyncHandler
    @asyncHandler
    func bar() {
    print(2)
    await foo1()
    print(4)
    await foo2()
    print(5)
    }
    print(1)
    bar()
    print(3)

    View Slide

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

    View Slide

  39. ໰୊ 05
    h"ps:/
    /swi)fiddle.com/rhtpvch3rreovbcgw757c3keem

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  44. Task
    func foo() async {
    // Task A
    await bar()
    // Task A
    await baz()
    // Task A
    }

    View Slide

  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
    }

    View Slide

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

    View Slide

  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
    }

    View Slide

  48. Task Tree શମͷΩϟϯηϧ
    func foo() async {
    // ෳࡶͳ Task Tree Λ࣋ͭඇಉظॲཧ
    }
    func bar() {
    let handle = Task.runDetached {
    await foo()
    }
    handle.cancel()
    }

    View Slide

  49. ໰୊ 06
    h"ps:/
    /swi)fiddle.com/mwjiy2f768ztaagrfrqs6lxhy

    View Slide

  50. ίʔϧόοΫ → async
    func foo(completion: @escaping (Int) -> Void) { ... }
    func foo() async -> Int {
    // ίʔϧόοΫ൛ͷ foo Λ࢖ͬͯͲ͏΍࣮ͬͯ૷͢Δʁ
    }

    View Slide

  51. ίʔϧόοΫ → async ʢ JS ʣ
    function fooCallback(completion) { ... }
    function fooAsync() {
    return new Promise((resolve) => {
    fooCallback(value => {
    resolve(value);
    });
    });
    }

    View Slide

  52. ίʔϧόοΫ → async ʢ Swi& ʣ
    func foo(completion: @escaping (Int) -> Void) { ... }
    func foo() async -> Int {
    await withUnsafeContinuation { continuation in
    foo { value in
    continuation.resume(returning: value)
    }
    }
    }

    View Slide

  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

    View Slide

  54. Con$nua$on
    • UnsafeContinuation
    • UnsafeThrowingContinuation
    • CheckedContinuation
    • CheckedThrowingContinuation

    View Slide

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

    View Slide

  56. UnsafeThrowingContinuation
    withUnsafeThrowingContinuation Ͱड͚औΔɻ
    struct UnsafeThrowingContinuation {
    func resume(returning: T)
    func resume(throwing: Error)
    func resume(with result: Result)
    }

    View Slide

  57. ໰୊ 07
    h"ps:/
    /swi)fiddle.com/tuu5w2k37jdu5:k6gv5>hcni

    View Slide

  58. ·ͱΊ
    • async/await (Accepted)
    • async let
    • @asyncHandler
    • Task.Handle
    • Con&nua&on (Ac)ve review)

    View Slide