Home > Back-end >  Composing sync and async functions in Swift 5.5
Composing sync and async functions in Swift 5.5

Time:07-08

Consider the following (silly) example:

func u () async -> UInt32 {
    let r =  UInt32(Int.random(in: 1...10))
    sleep(r)
    return r
}

func v(_ x: UInt32) -> UInt32 {
    x
}

Task.init{
    print(v(await u()))
    print(await v(u()))
    await print(v(u()))
}

All three lines in the task appear to work. Are they equivalent, or are there any pitfalls I should be aware of? Thanks.

CodePudding user response:

Like try, Swift allows you to place the await keyword on any part of an expression that contains an async method:

func ƒ<T>(_ v: T) -> T { v }


// All equivalent:
func somethingThatThrows() throws {}
print(ƒ(try somethingThatThrows()))
print(try ƒ(somethingThatThrows()))
try print(ƒ(somethingThatThrows()))


// All equivalent:
func someAsyncFunc() async {}
Task {
    print(ƒ(await someAsyncFunc()))
    print(await ƒ(someAsyncFunc()))
    await print(ƒ(someAsyncFunc()))
}

The Swift grammar reference for the await keyword does have an example for where placement of await does matter (awaiting only a subexpression of a whole expression that needs to be awaited), but it's not quite relevant here:

// await applies to both function calls
sum = await someAsyncFunction()   anotherAsyncFunction()

// await applies to both function calls
sum = await (someAsyncFunction()   anotherAsyncFunction())

// Error: await applies only to the first function call
sum = (await someAsyncFunction())   anotherAsyncFunction()
  • Related