[swift-evolution] [Concurrency] async/await + actors

Brent Royal-Gordon brent at architechies.com
Fri Aug 18 02:50:59 CDT 2017

> On Aug 17, 2017, at 11:59 PM, Félix Cloutier via swift-evolution <swift-evolution at swift.org> wrote:
> The purpose of `beginAsync` is to start an `async` function while firewalling against the propagation of the `async` keyword to the caller. `beginAsync` does not return a value. By the time `beginAsync` returns, whatever continuation closure was generated for the `body` parameter has been passed off to someone else and some scheduling mechanism has a reference to it and will call it later. That's not giving me too much trouble either.
> I'm somewhat bugged by `suspendAsync`. My understanding is that it allows you to take a synchronous function which accepts a callback and turn it into an asynchronous one, where "asynchronous" means "continuation-driven" more that "asynchronously executing", because something like `let foo: Int = await suspendAsync { $0(42) }` looks like it should be legal (although not particularly useful).
> The interaction of `suspendAsync` and `await` is that `suspendAsync`, like any other `async` function, accepts a hidden closure parameter, and `await` takes the rest of the function and turns it into a continuation closure to pass as that hidden parameter. The explicit parameters of `suspendAsync` are closures that accept the continuation (either for success or failure), so `suspendAsync` is the primitive that's responsible for translating the rest of an `async` function into something that you can pass as a callback.
> That seems to make sense to me (although I might have it wrong), but I'm having trouble with the terminology. I'm not trying to start a bike shed debate here; it's simply not immediately clear to me what "suspendAsync" means for a function that seems more about starting an "old world" asynchronous task than suspending anything (let alone an asynchronous thing).

I, too, didn't really get these at first, although the code samples illuminated things some for me.

`beginAsync(_:)` is a sort of poor man's `Future`—it guarantees that the async function will start, but throws away the return value, and *might* throw away the error unless it happens to get thrown early. Given that its ability to return information from the body is so limited, I frankly don't think it's worth making this function rethrow only some errors. I would instead make it accept only a non-throwing `async` function, and if you need to call something that throws, you can pass an async closure with a `do`/`catch` block.

`suspendAsync(_:)` essentially converts the async calling into completion-based calling, as you said. I'm not sure if there's *literally* an implicit completion closure or if they're doing something else—the proposal doesn't lay out the transformations the compiler performs in much detail. I don't want to open this up to bikeshedding, but I sort of think of this function as `runAsyncWithCompletionHandler(_:)` or, more idiomatically, `withAsyncCompletion(do:)`.

Brent Royal-Gordon

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170818/8b089be4/attachment.html>

More information about the swift-evolution mailing list