Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift 5.5 async let - error: expression is 'async' but is not marked with 'await'

WWDC21 introduces Swift 5.5, with async/await. Following the Explore structured concurrency in Swift and Meet async/await in Swift WWDC21 sessions, I'm trying to use the async let function.

Here's my Playground code:

func doIt() async -> String {
    let t = TimeInterval.random(in: 0.25 ... 2.0)
    Thread.sleep(forTimeInterval: t)
    return String("\(Double.random(in: 0...1000))")
}

async {
    async let a = doIt()
    async let b = doIt()
    async let c = doIt()
    async let d = doIt()
    
    let results = await [a, b, c, d]
    for result in results {
        print("  \(result)")
    }
}

However, for each of the "async let" lines, I get this error:

error: AsyncLetSwift55WWDC21.playground:12:15: error: expression is 'async' but is not marked with 'await'
    async let a = doIt()
              ^
              await 

Paul Hudson's blog showed this example: Hacking With Swift async let example

The Exploring structured currency video has this example at about the 8:10 mark: enter image description here

EDIT: This does seem to be a Playground-specific issue. Per the suggestion on the same issue in Apple Developer Forums, running the same code (ok, I did add sleep(10) to the end of the source file after the async block for macOS, so the app wouldn't terminate before the async calls completed) as a macOS command-line project gives no errors and produces the proper output.

Is this a bug, or am I just not understanding something?

like image 262
drewster Avatar asked Jun 10 '21 19:06

drewster


People also ask

Does Swift have async await?

Swift now supports asynchronous functions — a pattern commonly known as async/await. Discover how the new syntax can make your code easier to read and understand. Learn what happens when a function suspends, and find out how to adapt existing completion handlers to asynchronous functions.

How does async await work Swift?

Calling an asynchronous function with await runs only one piece of code at a time. While the asynchronous code is running, the caller waits for that code to finish before moving on to run the next line of code.

Does await blocks the next line?

Because await is only valid inside async functions and modules, which themselves are asynchronous and return promises, the await expression never blocks the main thread and only defers execution of code that actually depends on the result, i.e. anything after the await expression.

How do you write async function in Swift?

Although Swift functions are synchronous by default, we can make them asynchronous by adding one keyword: async . Inside asynchronous functions, we can call other asynchronous functions using a second keyword: await . As a result, you'll often hear Swift developers talk about async/await as a way of coding.


1 Answers

My advice would be: don't try this in a playground. Playgrounds aren't ready for this stuff yet. Your code compiles and runs fine in a real project. Here's an example:

class ViewController: UIViewController {
    
    func doIt() async -> String {
        let t = TimeInterval.random(in: 0.25 ... 2.0)
        Thread.sleep(forTimeInterval: t)
        return String("\(Double.random(in: 0...1000))")
    }
    func test() {
        async {
            async let a = doIt()
            async let b = doIt()
            async let c = doIt()
            async let d = doIt()
            
            let results = await [a, b, c, d]
            for result in results {
                print("  \(result)")
            }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        test()
    }
}
like image 140
matt Avatar answered Oct 19 '22 17:10

matt