<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 class="">(I changed the subject since it’s not really the same topic)</div><div class=""><br class=""></div><div class="">The short answer is that this code has the same problem even without async void:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">func sendMessage() {</div><div class="">&nbsp; &nbsp; beginAsync {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; // …</div><div class="">&nbsp; &nbsp; }</div><div class="">}</div><div class=""><font color="#5856d6" class=""><br class=""></font></div><div class="">func onButtonClick() {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>sendMessage()</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>showAlert("message sent")</div><div class=""><div dir="ltr" class=""><div class="">}</div></div></div></blockquote><div class=""><br class=""></div><div class="">If you want someone to be able to wait for something to finish then you make your function awaitable. So what does that mean for an async function that doesn’t really return anything? To understand what I’m thinking it helps to understand how C# does it, since that’s the model I’m proposing, and I think it works really well. In C# it works like this:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">void NoReturn() { }</div><div class="">int IntReturn() { return 0; }</div><div class=""><br class=""></div><div class="">async Task NoReturnAsync() { await Task.Yield(); }</div><div class="">async Task&lt;int&gt; IntReturnAsync() { await Task.Yield(); return 0; }</div><div class=""><br class=""></div><div class="">async void NoReturnAsyncVoid() { await Task.Yield(); }</div><div class=""><br class=""></div><div class="">async Task Caller()</div><div class="">{</div><div class="">&nbsp; &nbsp; NoReturn();</div><div class="">&nbsp; &nbsp; int i = IntReturn();</div><div class="">&nbsp; &nbsp; await NoReturnAsync();</div><div class="">&nbsp; &nbsp; int j = await IntReturnAsync();</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; NoReturnAsync(); // this cannot be awaited</div><div class="">}</div></blockquote><div class=""><br class=""></div>An important difference is that in C# the async keyword does not make a function awaitable. Notice how NoReturnAsyncVoid is marked as “async”, but the caller cannot use “await” with it. So what do you do if you want to wait for it to finish, like in your example? Well notice that another function NoReturnAsync doesn’t actually appear to return anything, even though its return type is Task. The compiler transforms the function into pieces where the first piece (the one actually called by the caller) returns a Task object. A bare Task is only used for waiting for completion, whereas a Task&lt;T&gt; also holds a return value. When you make a function that returns T async then you change the return type to Task&lt;T&gt;. When you make a void function async and want to allow the caller to wait for it to finish then you change the void to Task. When you make a void function async but want the caller to not wait for it to finish then you leave it as void.<div class=""><br class=""></div><div class="">This is subtle, but consider this alternative form:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class="">void NoReturn() { }</div><div class="">int IntReturn() { return 0; }</div><div class=""><br class=""></div><div class="">Task NoReturnAsync() { return Task.Yield(); }</div><div class="">Task&lt;int&gt; IntReturnAsync() { return Task.Yield(); return 0; }</div><div class=""><br class=""></div><div class="">void NoReturnAsyncVoid() { Task.Yield(); }</div><div class=""><br class=""></div><div class="">async Task Caller()</div><div class="">{</div><div class="">&nbsp; &nbsp; NoReturn();</div><div class="">&nbsp; &nbsp; int i = IntReturn();</div><div class="">&nbsp; &nbsp; await NoReturnAsync();</div><div class="">&nbsp; &nbsp; int j = await IntReturnAsync();</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; NoReturnAsync(); // this cannot be awaited</div><div class="">}</div></div></blockquote><div class=""><br class=""></div>I changed all of the “async" functions above except for Caller by removing the “async” keyword and (where applicable) added return statements. Now none of those functions is async, but they are functionally equivalent. Notice that the async Caller (which I didn’t change at all) can still await the ones that return Task or Task&lt;T&gt;. That’s because, again, in C# the async keyword does not mean “this can be awaited”. Being able to await a function call is orthogonal to whether that function is marked as async.<div class=""><br class=""></div><div class="">Async means only one thing: that function can use the await keyword, and it will be decomposed by the compiler accordingly. So what can you await? Anything that’s “awaitable”. :) Basically if the return type of the function has a GetAwaiter method that returns a type that has a few properties and methods then you can use await on that function. This is described here: &lt;<a href="https://blogs.msdn.microsoft.com/pfxteam/2011/01/13/await-anything/" class="">https://blogs.msdn.microsoft.com/pfxteam/2011/01/13/await-anything/</a>&gt;. Task happens to have a GetAwaiter (&lt;<a href="https://msdn.microsoft.com/en-us/library/system.threading.tasks.task.getawaiter(v=vs.110).aspx" class="">https://msdn.microsoft.com/en-us/library/system.threading.tasks.task.getawaiter(v=vs.110).aspx</a>&gt;) method that returns a TaskAwaiter (&lt;<a href="https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.taskawaiter(v=vs.110).aspx%3E)" class="">https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.taskawaiter(v=vs.110).aspx&gt;)</a>, which happens to have an IsCompleted property and GetResult and OnCompleted methods.</div><div class=""><br class=""></div><div class="">You can make any type awaitable by supplying a suitable GetAwaiter implementation, even using an extension method. I think this could probably be done with protocols and extensions in Swift.</div><div class=""><br class=""></div><div class="">Back to the problem you described: wouldn’t an async void method be confusing to callers who expect it to finish before returning? Obviously if it’s a function that requires the caller to wait before continuing then it should be made awaitable. So in C# you wouldn’t make an async void function that you expected people to want to wait for, and in C# you have that choice: you can make an awaitable function that returns nothing to the awaiter.</div><div class=""><br class=""></div><div class="">The question, though, is “are there any use cases for an async function that doesn’t require its caller to wait for it?” Or, put another way, is there a use case for an async function that a caller can call as if it’s just any other void function? There definitely are multiple use cases for that, but the most important one probably is event callbacks, most often UI event callbacks. Think of a button click handler. When a button is clicked maybe you want to start some async task. This is a common pattern in .Net:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">private async void OnButtonClicked(object sender, EventArgs e)</div><div class="">{</div><div class="">&nbsp; &nbsp; Button button = (Button)sender;</div><div class="">&nbsp; &nbsp;&nbsp;button.IsEnabled = false;</div><div class="">&nbsp; &nbsp; await DoSomethingAsync();</div><div class="">&nbsp; &nbsp;&nbsp;button.IsEnabled = true;</div><div class="">}</div></blockquote><div class=""><br class=""></div>In Swift with the current proposal that would be something like this:<div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">func OnButtonClicked(_ sender:AnyObject) {</div></blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">&nbsp; &nbsp; let button = sender as! UIButton</div><div class="">&nbsp; &nbsp; button.isEnabled = false</div><div class="">&nbsp; &nbsp; beginAsync {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; await DoSomethingAsync()</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; button.isEnabled = true</div><div class="">&nbsp; &nbsp; }</div><div class="">}</div></blockquote><div class=""><br class=""></div>If you compare those two implementations I think it’s obvious which one is clearer. The advantage of async/await is that it makes async code look like sync code by preserving the logical code flow. It makes the compiler do the hard work of splitting the function up. If you have to use beginAsync then you’re forced to do what the compiler could do for you. You have to think about where it goes, and how much should be inside that block or outside. Someone might be tempted to write that method above like this:<div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">func OnButtonClicked(_ sender:AnyObject) {</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">&nbsp; &nbsp; let button = sender as! UIButton<br class="">&nbsp; &nbsp; button.isEnabled = false</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">&nbsp; &nbsp; beginAsync {</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; await DoSomethingAsync()<br class="">&nbsp; &nbsp; }</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">&nbsp; &nbsp; button.isEnabled = true<br class=""><div class="">}</div></blockquote><div class=""><br class=""></div>That code would be wrong. Is that obvious at a glance? I don’t think so. What about this?<div class=""><br class=""></div><div class=""><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class="">func OnButtonClicked(_ sender:AnyObject) {</blockquote><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class="">&nbsp; &nbsp; beginAsync {</blockquote><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; let button = sender as! UIButton<br class="">&nbsp; &nbsp; &nbsp; &nbsp; button.isEnabled = false</blockquote><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; await DoSomethingAsync()</blockquote><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; button.isEnabled = true<br class="">&nbsp; &nbsp; }</blockquote><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div class="">}</div></blockquote></div><div class=""><br class=""></div><div class="">That code does the right thing. So why wouldn’t you always write it that way? Serious question: what is the use case for using beginAsync for only part of a function? It looks like every example in Chris’s proposal wraps the entire contents of the function (except for one in an initializer).</div><div class=""><br class=""></div><div class="">If beginAsync is used almost exclusively to wrap the entire contents of void functions that you want to be async then why wouldn’t we just make it possible to make that function itself async and use await directly? It seems much clearer to me. async/await is already kind of confusing for newcomers, and I think beginAsync makes it worse by introducing a new concept that is easily misused and shouldn’t be necessary.</div><div class=""><div class=""><div class=""><div class=""><div class=""><div class=""><div class=""><div><br class=""></div><div><blockquote type="cite" class=""><div class="">On Nov 7, 2017, at 10:22 PM, omochi.metaru &lt;<a href="mailto:omochi.metaru@gmail.com" class="">omochi.metaru@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="">I totally agree Yuta's suggestion.</div><div class="">beginAsync does not have to accept function which throws.</div><div class=""><br class=""></div><div class="">&gt; Adam</div><div class=""><br class=""></div><div class="">I don't think that C# style async void function invodation matchs swift.</div><div class=""><br class=""></div><div class="">If we can do, following code can be compile.</div><div class=""><br class=""></div><div class="">```swift</div><div class="">async func sendMessage() -&gt; Void { ... }</div><div class=""><br class=""></div><div class="">func onButtonClick() {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>sendMessage()</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>showAlert("message sent")</div><div class="">}</div><div class="">```</div><div class=""><br class=""></div><div class="">But in this case, the logic actually programmer desired is&nbsp;</div><div class="">showing alert after sendMessage completed.</div><div class="">Above style code is not easy readable about execution fall through</div><div class="">without waiting completion of sendMessage to showAlert.</div><div class="">With this rule, compiler can not help us to find such mistaken code.</div><div class=""><br class=""></div><div class="">This seems like unchecked exception problem in other languages.</div><div class="">Keep starting asynchronous invodation explicit suck like&nbsp;</div><div class="">throwing function invocation explicitly marked with `try` or `do`.</div></div><br class=""><div class="gmail_quote"><div dir="ltr" class="">2017年11月8日(水) 13:28 Adam Kemp via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt;:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I think I agree with this. beginAsync is similar to C#’s async void functions, and one of the gotchas in C# is that it is never safe to allow an exception to be thrown from an async void function. The reason is that if the exception happens after the continuation then there won’t be any application code above it to catch that exception. As a result, the built in behavior is to immediately crash the app.<br class="">
<br class="">
This is unavoidable in C# where it’s impossible to write a function that is guaranteed not to throw. The semantics of exception throwing don’t allow for that in C#.<br class="">
<br class="">
Swift has the advantage in this case of being able to statically verify that a function doesn’t throw so we can do better.<br class="">
<br class="">
So I would argue in favor of not allowing beginAsync to throw at all.<br class="">
<br class="">
FWIW, I also still think it would be better if we allowed for async void functions instead of requiring beginAsync in the first place. If I had my way then we would have async void, but an async void would not be allowed to throw.<br class="">
<br class="">
&gt; On Nov 7, 2017, at 7:04 PM, Yuta Koshizawa via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:<br class="">
&gt;<br class="">
&gt; Although I posted about this topic before, let me post this again<br class="">
&gt; because I think it is important and I have received just few replies.<br class="">
&gt; Sorry if I missed some discussion about it.<br class="">
&gt;<br class="">
&gt; In the proposal (<br class="">
&gt; <a href="https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619" rel="noreferrer" target="_blank" class="">https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619</a> ),<br class="">
&gt; `beginAsync` has the following signature.<br class="">
&gt;<br class="">
&gt; ```<br class="">
&gt; func beginAsync(_ body: () async throws -&gt; Void) rethrows -&gt; Void<br class="">
&gt; ```<br class="">
&gt;<br class="">
&gt; However, I think it is better to forbid `body` to throw errors, that<br class="">
&gt; is to say, to change its signature to the following one.<br class="">
&gt;<br class="">
&gt; ```<br class="">
&gt; func beginAsync(_ body: () async -&gt; Void) -&gt; Void<br class="">
&gt; ```<br class="">
&gt;<br class="">
&gt; Even if `beginAsync` allows that `body` throws errors, it can rethrow<br class="">
&gt; ones which are thrown before only first `await` call. In following<br class="">
&gt; cases, `beginAsync` just has to make the program crash when `foo`<br class="">
&gt; throws an error. It breaks safety for error handing by typed<br class="">
&gt; propagation realized by `throws/try`.<br class="">
&gt;<br class="">
&gt; ```<br class="">
&gt; // throws errors asynchronously<br class="">
&gt; func foo() async throws -&gt; Int { ... }<br class="">
&gt;<br class="">
&gt; do {<br class="">
&gt;&nbsp; &nbsp; beginAsync {<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; let a = try await foo()<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; // uses `a` here<br class="">
&gt;&nbsp; &nbsp; }<br class="">
&gt; } catch _ {<br class="">
&gt;&nbsp; &nbsp; // never reaches here<br class="">
&gt; }<br class="">
&gt; ```<br class="">
&gt;<br class="">
&gt; If `beginAsync` forbid `body` to throw errors, it can be detected as a<br class="">
&gt; compilation error and is possible to fix it as follows.<br class="">
&gt;<br class="">
&gt; ```<br class="">
&gt; beginAsync {<br class="">
&gt;&nbsp; &nbsp; do {<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; let a = try await foo()<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; // uses `a` here<br class="">
&gt;&nbsp; &nbsp; } catch _ {<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; //&nbsp; error handling<br class="">
&gt;&nbsp; &nbsp; }<br class="">
&gt; }<br class="">
&gt; ```<br class="">
&gt;<br class="">
&gt; And even when we want to write `try` calls in `beginAsync` before<br class="">
&gt; first `await` call, those lines can be moved before the `beginAsync`<br class="">
&gt; call.<br class="">
&gt;<br class="">
&gt; ```<br class="">
&gt; // before ( `beginAsync` marked with `rethrows` )<br class="">
&gt; do {<br class="">
&gt;&nbsp; &nbsp; beginAsync {<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; let a = try bar()<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; let b = try baz()<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; let c = await qux(a, b)<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; // uses `c` here<br class="">
&gt;&nbsp; &nbsp; }<br class="">
&gt; catch _ {<br class="">
&gt;&nbsp; &nbsp; // error handling<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; // after ( `beginAsync` without `rethrows` )<br class="">
&gt; do {<br class="">
&gt;&nbsp; &nbsp; let a = try bar()<br class="">
&gt;&nbsp; &nbsp; let b = try baz()<br class="">
&gt;&nbsp; &nbsp; beginAsync {<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; let c = await qux(a, b)<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; // uses `c` here<br class="">
&gt;&nbsp; &nbsp; }<br class="">
&gt; catch _ {<br class="">
&gt;&nbsp; &nbsp; // error handling<br class="">
&gt; }<br class="">
&gt; ```<br class="">
&gt;<br class="">
&gt; So the functionalities of `beginAsync` seems be kept even if it forbid<br class="">
&gt; `body` to throw errors.<br class="">
&gt;<br class="">
&gt; What do you think about it?<br class="">
&gt;<br class="">
&gt; --<br class="">
&gt; Yuta<br class="">
&gt; _______________________________________________<br class="">
&gt; swift-evolution mailing list<br class="">
&gt; <a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class="">
&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
</blockquote></div><div dir="ltr" class="">-- <br class=""></div><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr" class=""><div class="">omochimetaru</div></div></div>
</div></blockquote></div><br class=""></div></div></div></div></div></div></div></body></html>