[swift-evolution] [Concurrency] Async/Await

Goffredo Marocchi panajev at gmail.com
Tue Aug 22 11:42:52 CDT 2017


Just to get it out of the way and to put the issue down... assuming we could get something like Promises and Futures, how much experience do people have with how async and await + Promises are changing the asynchronous by nature JavaScript? What in there really does not work and should one of the layer we provide be similar to it?

Sent from my iPhone

> On 22 Aug 2017, at 17:32, Joe Groff via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
>> On Aug 21, 2017, at 10:21 PM, David Hart <david at hartbit.com> wrote:
>> 
>> Sorry for the shameless bump :-/ but I’d love to get some answers so I can better understand the proposal and participate in the discussions.
>> 
>>> On 21 Aug 2017, at 07:58, David Hart via swift-evolution <swift-evolution at swift.org> wrote:
>>> 
>>> Hello,
>>> 
>>> Thanks for the great work on the async/await proposal! After reading it, I have a few questions and comments about it, so I’m creating this thread to concentrate on that topic (instead of Actors).
>>> 
>>> Generators
>>> 
>>> The proposal mentions in Problem 6 of the Motivation how generators can help write sequences:
>>> 
>>> In contrast, languages that have generators allow you to write something more close to this:
>>> 
>>> func getSequence() -> AnySequence<Int> {
>>>     let seq = sequence {
>>>         for i in 1...10 {
>>>             yield(i*i)
>>>         }
>>>     }
>>>     return AnySequence(seq)
>>> }
>>> 
>>> This feels very similar to me from C# where the yield keyword is used to support the generator feature. But I fail to see how the coroutines as described in this proposal resolve this problem. Can someone explain?
> 
> The feature provides general delimited continuations. You could write an IteratorProtocol-conforming interface over a coroutine like this:
> 
> class Generator<T>: IteratorProtocol {
>  var next: T? = nil
>  var resume: (() -> ())? = nil
> 
>  init(_ body: (_ yield: @escaping (T) async -> Void) -> Void) {
>    self.resume = {
>      beginAsync {
>        body(self.yield)
>      }
>  }
> 
>  func next() -> T? {
>    if let resume = self.resume {
>      resume()
>      return self.next
>    }
>    return nil
>  }
> 
>  private func yield(_ value: T) async -> Void {
>    self.next = value
>    await suspendAsync { cont in
>      resume = cont
>    }
>  }
> }
> 
> let fibs = Generator { yield in
>  var (a, b) = (0, 1)
>  while a < 1000 {
>    await yield(a)
>    (a, b) = (b, a + b)
>  }
> }
> 
> This isn't ideal in a number of ways (awkward, not particularly efficient, and has the gotcha that the generator's `body` could suspend itself with something other than the `yield` operation, doesn't integrate with ownership in the way John proposes in the ownership manifesto), so it may not be a good idea, of course.
> 
>>> beginAsync
>>> 
>>> The documentation of the beginAsync and suspendAsync functions state:
>>> 
>>> // NB: Names subject to bikeshedding. These are low-level primitives that most
>>> // users should not need to interact with directly, so namespacing them
>>> // and/or giving them verbose names unlikely to collide or pollute code
>>> // completion (and possibly not even exposing them outside the stdlib to begin
>>> // with) would be a good idea.
>>> 
>>> But I don’t understand how they can be kept private to the standard library when they are used for the important pattern of spawning off an async operation from a non-async function:
> 
> beginAsync provides raw material for starting an async process, but I think you'd often want to wrap it up in something more interesting, like a DispatchQueue method that enqueues the coroutine on a specific queue, a Future constructor that captures the eventual result, etc. Nonetheless, I removed this statement from the proposal.
> 
>>> Despite these problems, it is essential that the model encompasses this pattern, because it is a practical necessity in Cocoa development. With this proposal, it would look like this:
>>> 
>>> @IBAction func buttonDidClick(sender:AnyObject) {
>>>   // 1
>>>   beginAsync {
>>>     // 2
>>>     let image = await processImage()
>>>     imageView.image = image
>>>   }
>>>   // 3
>>> Futures
>>> 
>>> When discussing futures, the proposal states:
>>> 
>>> The exact design for a future type deserves its own proposal, but a proof of concept could look like this:
>>> 
>>> Does that sentence imply that the Core Team would welcome a Future implementation into the Standard Library?
> 
> It's worth discussing. My personal feeling is that a lot of the things people do with futures can potentially be done better with other coordination primitives, but we'll see.
> 
>>> async as a subtype of throws instead of orthogonal to it
>>> 
>>> I’ve been thinking a lot about this since the proposal came out and I see a few serious disadvantages at making async a subtype of throws which might benefit from being discussed or/and mentioned in the proposal.
>>> 
>>> 1. We loose the automatic documentation try provides for signaling failable functions:
>>> 
>>> let image = await downloadImage()
>>> let processedImage = await processImage(image)
>>> await present(MyViewController(image: image))
>>> 
>>> In my example, downloadImage can fail because of network conditions, processImage can not fail, and present is the UIKit function which presents view controllers and it can’t fail either. But that’s not obvious from reading the code. We’ve lost information.
> 
> This seems like a similar pitfall to too narrow exception types that we try to avoid with `throws`. Saying that even a long-lived computation like processImage can't throw is a brittle architectural choice, since you may need to build in support for cancellation at some point, and if you ever decide to offload the computation to a GPU, coprocessor, or out-of-process worker, then it will be able to fail at that point. It's not clear to me why `present` would be async here; it seems to me like a fire-and-forget kind of operation you don't want to wait for.
> 
> -Joe
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170822/2b07f5f2/attachment-0001.html>


More information about the swift-evolution mailing list