[swift-evolution] async void

Yuta Koshizawa koher at koherent.org
Fri Nov 10 03:38:05 CST 2017


> I’m not sure how the proposed design handles type checking for async
> closures. Is async part of the type? Can I declare a local closure variable
> as async? What are the rules for conversion between async and non-async
> closures? Is it a warning or error to use a closure literal without an async
> keyword that is assigned to an async closure variable or passed as an async
> closure argument?

It has been already realized for `throws`.

```
// This works in Swift 4
func foo(_ f: (Bar) throws -> Baz)

// This can be checked in the same way
func foo(_ f: (Bar) async -> Baz)
```

Proposed `async/await` in Swift are analogous to `throws/try`. So a
lot of things about `async/await` can be imagined when we think about
`throws/try`. It is also true for `(Foo) async -> Void`. We can use it
in the same way as we use `(Foo) throws -> Void`.

`async/await` as an analogy to `throws/try` works well because both of
them can be mapped to monads. `throws` is similar to `Result` and
`async` is similar to `Promise` ( `Future` ).

```
// `a` and `b` are similar
func a() throws -> Int
func b() -> Result<Int>

// `c` and `d` are similar
func c() async -> Int
func d() -> Promise<Int>

// `a` : `b` == `c` : `d`
// `a` : `c` == `b` : `d`
```

`try` and `await` are also similar to `flatMap`. ( I think most
popular `Promise` is one in JavaScript. Although it does not have
`flatMap`, its `then` method can be considered as `flatMap`. )

```
let x = try a()
// uses `x` here

b().flatMap { x in
  // uses `x` here
}

let y = await c()
// uses `y` here

d().flatMap { y in
  // uses `y` here
}
```

So `throws` : `try` : `Result` == `async` : `await` : `Promise` and
`throws` : `async` == `try` : `await` == `Result` : `Promise`. I think
those relations are beautiful and proposed `async/await` fits well to
Swift because we have already had `throws/try`.

--
Yuta


2017-11-10 6:45 GMT+09:00 Adam Kemp via swift-evolution
<swift-evolution at swift.org>:
>
> On Nov 9, 2017, at 11:02 AM, Wallacy <wallacyf at gmail.com> wrote:
>
> So for me, this:
>
> func OnButtonClicked(_ sender:AnyObject) {
>
>     let button = sender as! UIButton
>     button.isEnabled = false
>     beginAsync {
>         await DoSomethingAsync()
>         button.isEnabled = true
>     }
> }
>
>
> Does not make any sense... Because await will not block the thread we can
> assume (like the exemple on proposal) that compiler will actually do the
> same what we will do using GDC and pick everyone to until the context ends
> and encapsulate as completion handle to the away call.
>
>
> I don’t understand what you’re saying here. In terms of GCD the above code
> is basically equivalent to this:
>
> func buttonClicked(_ sender:AnyObject) {
>     let button = sender as! UIButton
>     button.isEnabled = false
>     doSomethingAsync { // completion callback, assume it’s on the main queue
>         button.isEnabled = true
>     }
> }
>
>
> And this one:
>
> @IBAction func buttonDidClick(sender:AnyObject) {
>   beginAsync {
>     let image = await processImageData()
>     // Do the update on the main thread/queue since it owns imageView.
>     mainQ.async {
>       imageView.image = image
>     }
>   }
> }
>
>
>
> Does not make any sense too.
>
> The only way to await to do not block the thread is make a early return like
> beginAsync and encapsulate as completion handle the rest of the code.
>
>
> This is why “await” can only be used in a function that is marked as
> “async”. The “async” keyword tells the compiler that this function will be
> broken up into parts, and its return value will be produced asynchronously.
>
> One thing that might be confusing is that in the examples using “beginAsync”
> the trailing closure is the async function. That’s not obvious because
> there’s no “async” keyword, but it’s there in the signature of the closure
> argument:
>
> func beginAsync(_ body: () async throws -> Void) rethrows -> Void
>
>
> I’m not sure how the proposed design handles type checking for async
> closures. Is async part of the type? Can I declare a local closure variable
> as async? What are the rules for conversion between async and non-async
> closures? Is it a warning or error to use a closure literal without an async
> keyword that is assigned to an async closure variable or passed as an async
> closure argument?
>
> C# dodges all of these issues because async isn't part of the type system.
> Closures that don’t return anything can be declared async just like void
> functions, and code that uses void-returning closures doesn’t need to care
> whether the implementation is async or not.
>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>


More information about the swift-evolution mailing list