<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">I’m not sure that answered my questions.<div class=""><br class=""></div><div class="">Can I do this?</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">let asyncClosure:() async -&gt; Void = { await doSomethingAsync() } // Can you declare an async closure variable?</div><div class=""><br class=""></div><div class="">beginAsync(asyncClosure)</div></blockquote><div class=""><br class=""></div><div class="">What about this?</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">let syncClosure:() -&gt; Void = { doSomethingSync() }</div><div class=""><br class=""></div><div class="">beginAsync(syncClosure) // Can a non-async closure be passed to a function expecting a async closure?</div></blockquote><div class=""><br class=""></div>And this?<blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><br class=""></div></blockquote><div class=""><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">func callSyncClosure(_ closure:() -&gt; ()) { closure() }</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><br class=""></blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">let asyncClosure:() async -&gt; Void = { await doSomethingAsync() }</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><br class=""></blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">callSyncClosure(asyncClosure) // Can an async closure be passed to a function expecting a non-async closure?</blockquote><div class=""><br class=""></div>Here are my thoughts on each of these:</div><div class=""><br class=""></div><div class="">Can you declare an async closure variable? If async is part of the type then it would be very strange not to allow this. I think the proposal implies that you can, but only by way of an example about inferring whether a closure is async or not.</div><div class=""><br class=""></div><div class="">Can a non-async closure be passed to a function expecting a sync closure? This seems like an obvious conversion. I feel like disallowing this would probably make things harder, but I haven’t thought it through enough to say exactly how. Are there reasons that this shouldn’t work, though?</div><div class=""><br class=""></div><div class="">Can an async closure be passed to a function expecting a sync closure? This may be controversial, but I think this should be allowed too. I think a caller that expects a void-returning synchronous function should be able to call an async function and treat it as a call-and-forget.</div><div class=""><br class=""></div><div class="">It’s weird to me that we would allow you to have async void closures but not async void functions, but in order to support beginAsync we have to have async void closures. So if we can make that work then why couldn’t we just make async void functions work and dispense with beginAsync entirely?</div><div class=""><div class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Nov 10, 2017, at 1:38 AM, Yuta Koshizawa via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><blockquote type="cite" class="">I’m not sure how the proposed design handles type checking for async<br class="">closures. Is async part of the type? Can I declare a local closure variable<br class="">as async? What are the rules for conversion between async and non-async<br class="">closures? Is it a warning or error to use a closure literal without an async<br class="">keyword that is assigned to an async closure variable or passed as an async<br class="">closure argument?<br class=""></blockquote><br class="">It has been already realized for `throws`.<br class=""><br class="">```<br class="">// This works in Swift 4<br class="">func foo(_ f: (Bar) throws -&gt; Baz)<br class=""><br class="">// This can be checked in the same way<br class="">func foo(_ f: (Bar) async -&gt; Baz)<br class="">```<br class=""><br class="">Proposed `async/await` in Swift are analogous to `throws/try`. So a<br class="">lot of things about `async/await` can be imagined when we think about<br class="">`throws/try`. It is also true for `(Foo) async -&gt; Void`. We can use it<br class="">in the same way as we use `(Foo) throws -&gt; Void`.<br class=""><br class="">`async/await` as an analogy to `throws/try` works well because both of<br class="">them can be mapped to monads. `throws` is similar to `Result` and<br class="">`async` is similar to `Promise` ( `Future` ).<br class=""><br class="">```<br class="">// `a` and `b` are similar<br class="">func a() throws -&gt; Int<br class="">func b() -&gt; Result&lt;Int&gt;<br class=""><br class="">// `c` and `d` are similar<br class="">func c() async -&gt; Int<br class="">func d() -&gt; Promise&lt;Int&gt;<br class=""><br class="">// `a` : `b` == `c` : `d`<br class="">// `a` : `c` == `b` : `d`<br class="">```<br class=""><br class="">`try` and `await` are also similar to `flatMap`. ( I think most<br class="">popular `Promise` is one in JavaScript. Although it does not have<br class="">`flatMap`, its `then` method can be considered as `flatMap`. )<br class=""><br class="">```<br class="">let x = try a()<br class="">// uses `x` here<br class=""><br class="">b().flatMap { x in<br class=""> &nbsp;// uses `x` here<br class="">}<br class=""><br class="">let y = await c()<br class="">// uses `y` here<br class=""><br class="">d().flatMap { y in<br class=""> &nbsp;// uses `y` here<br class="">}<br class="">```<br class=""><br class="">So `throws` : `try` : `Result` == `async` : `await` : `Promise` and<br class="">`throws` : `async` == `try` : `await` == `Result` : `Promise`. I think<br class="">those relations are beautiful and proposed `async/await` fits well to<br class="">Swift because we have already had `throws/try`.<br class=""><br class="">--<br class="">Yuta<br class=""><br class=""><br class="">2017-11-10 6:45 GMT+09:00 Adam Kemp via swift-evolution<br class="">&lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt;:<br class=""><blockquote type="cite" class=""><br class="">On Nov 9, 2017, at 11:02 AM, Wallacy &lt;<a href="mailto:wallacyf@gmail.com" class="">wallacyf@gmail.com</a>&gt; wrote:<br class=""><br class="">So for me, this:<br class=""><br class="">func OnButtonClicked(_ sender:AnyObject) {<br class=""><br class=""> &nbsp;&nbsp;&nbsp;let button = sender as! UIButton<br class=""> &nbsp;&nbsp;&nbsp;button.isEnabled = false<br class=""> &nbsp;&nbsp;&nbsp;beginAsync {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;await DoSomethingAsync()<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;button.isEnabled = true<br class=""> &nbsp;&nbsp;&nbsp;}<br class="">}<br class=""><br class=""><br class="">Does not make any sense... Because await will not block the thread we can<br class="">assume (like the exemple on proposal) that compiler will actually do the<br class="">same what we will do using GDC and pick everyone to until the context ends<br class="">and encapsulate as completion handle to the away call.<br class=""><br class=""><br class="">I don’t understand what you’re saying here. In terms of GCD the above code<br class="">is basically equivalent to this:<br class=""><br class="">func buttonClicked(_ sender:AnyObject) {<br class=""> &nbsp;&nbsp;&nbsp;let button = sender as! UIButton<br class=""> &nbsp;&nbsp;&nbsp;button.isEnabled = false<br class=""> &nbsp;&nbsp;&nbsp;doSomethingAsync { // completion callback, assume it’s on the main queue<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;button.isEnabled = true<br class=""> &nbsp;&nbsp;&nbsp;}<br class="">}<br class=""><br class=""><br class="">And this one:<br class=""><br class="">@IBAction func buttonDidClick(sender:AnyObject) {<br class=""> &nbsp;beginAsync {<br class=""> &nbsp;&nbsp;&nbsp;let image = await processImageData()<br class=""> &nbsp;&nbsp;&nbsp;// Do the update on the main thread/queue since it owns imageView.<br class=""> &nbsp;&nbsp;&nbsp;mainQ.async {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imageView.image = image<br class=""> &nbsp;&nbsp;&nbsp;}<br class=""> &nbsp;}<br class="">}<br class=""><br class=""><br class=""><br class="">Does not make any sense too.<br class=""><br class="">The only way to await to do not block the thread is make a early return like<br class="">beginAsync and encapsulate as completion handle the rest of the code.<br class=""><br class=""><br class="">This is why “await” can only be used in a function that is marked as<br class="">“async”. The “async” keyword tells the compiler that this function will be<br class="">broken up into parts, and its return value will be produced asynchronously.<br class=""><br class="">One thing that might be confusing is that in the examples using “beginAsync”<br class="">the trailing closure is the async function. That’s not obvious because<br class="">there’s no “async” keyword, but it’s there in the signature of the closure<br class="">argument:<br class=""><br class="">func beginAsync(_ body: () async throws -&gt; Void) rethrows -&gt; Void<br class=""><br class=""><br class="">I’m not sure how the proposed design handles type checking for async<br class="">closures. Is async part of the type? Can I declare a local closure variable<br class="">as async? What are the rules for conversion between async and non-async<br class="">closures? Is it a warning or error to use a closure literal without an async<br class="">keyword that is assigned to an async closure variable or passed as an async<br class="">closure argument?<br class=""><br class="">C# dodges all of these issues because async isn't part of the type system.<br class="">Closures that don’t return anything can be declared async just like void<br class="">functions, and code that uses void-returning closures doesn’t need to care<br class="">whether the implementation is async or not.<br class=""><br class=""><br class=""><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""><br class=""></blockquote>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></div></blockquote></div><br class=""></div></div></div></body></html>