<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="">However, equally important to the case I was making earlier is that you should be able to call an “async Never” function as if it were a non-async Void function. This is especially important for cases where you want to pass a callback to something (like an event handler), and you want the callback to be able to use await. So as long as that still works I could live with "async Never”.<br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Nov 13, 2017, at 9:49 AM, Adam Kemp &lt;<a href="mailto:adam_kemp@apple.com" class="">adam_kemp@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">I kind of like that idea. I’d rather have a Task/Future/Promise/whatever, but if that’s not going to happen then Void vs. Never seems like a reasonable way of distinguishing these two cases.<br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Nov 12, 2017, at 9:55 AM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">Sorry, I'm just getting into this conversation late and am by no means experienced in the area, but why can't the one where you *don't* want the caller to wait for the result be spelled `async -&gt; Never`? Theoretically, `async -&gt; Void` means you're awaiting a result with only one possible value, but if you're not waiting at all, then there is truly no result, yes?<div class=""><br class=""><div class="gmail_extra"><br class=""><div class="gmail_quote">On Sun, Nov 12, 2017 at 9:27 AM, Yuta Koshizawa via swift-evolution <span dir="ltr" class="">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt;</span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Sorry, I had got some confusion. Please let me retry to explain.<br class="">
<br class="">
As you said, C# provides three kinds of async functions: `async Void`,<br class="">
`async Task` and `async Task&lt;Foo&gt;`. All of them are necessary and<br class="">
Swift should provide same functionalities.<br class="">
<br class="">
When we think about `async/await` in Swift, because we have already<br class="">
had `throws/try`, it is desired that `async/await` in Swift is<br class="">
consistent with `throws/try`. So it is better to have `async/await`<br class="">
without introducing a type like `Task` (or `Promise`).<br class="">
<br class="">
Even if we employ `async/await` without `Task`, Swift has to provides<br class="">
functionalities to implement "three kinds of async functions" in C#.<br class="">
However if `async -&gt; Void` in Swift works similarly to `async Void` in<br class="">
C#, how can we express ones like `async Task` in C#? I think there are<br class="">
two possibilities:<br class="">
<br class="">
1. Calling `async -&gt; Void` functions without `await` in Swift works<br class="">
like `async Void` in C# and calling them *with* `await` works like<br class="">
`async Task` in C#.<br class="">
2. Calling `async -&gt; Void` functions without `await` in Swift works<br class="">
like `async Void` in C# and never support something like `async Task`<br class="">
in C#.<br class="">
<br class="">
I think 2 is impermissible. For example, handling completion events of<br class="">
asynchronous operations without result values needs something like<br class="">
`async Task` in C#. However, with 1, we lose the benefit of static<br class="">
checks by the compiler. Because both of `fooAsync()` without `await`<br class="">
and `await fooAsync()` are allowed, even if we want it to work like<br class="">
`async Task` in C# and forget to mark `await`, the compiler tell us<br class="">
nothing and it works like `async Void` in C#. It causes unexpected<br class="">
behaviors. It is hard to fix such kinds of bugs. So I think<br class="">
introducing `beginAsync` is better.<br class="">
<br class="">
--<br class="">
Yuta<br class="">
<br class="">
<br class="">
2017-11-12 10:23 GMT+09:00 Yuta Koshizawa via swift-evolution<br class="">
&lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt;:<br class="">
<div class="HOEnZb"><div class="h5">&gt; 2017-11-12 2:57 GMT+09:00 Adam Kemp &lt;<a href="mailto:adam.kemp@apple.com" class="">adam.kemp@apple.com</a>&gt;:<br class="">
&gt;&gt;<br class="">
&gt;&gt;<br class="">
&gt;&gt;&gt; On Nov 11, 2017, at 6:24 AM, Yuta Koshizawa &lt;<a href="mailto:koher@koherent.org" class="">koher@koherent.org</a>&gt; wrote:<br class="">
&gt;&gt;&gt;<br class="">
&gt;&gt;&gt; If you replace `async` with `throws`, you can get answers.<br class="">
&gt;&gt;&gt;<br class="">
&gt;&gt;&gt;<br class="">
&gt;&gt;&gt;&gt; Can you declare an async closure variable?<br class="">
&gt;&gt;&gt;<br class="">
&gt;&gt;&gt; Yes. Like `let throwingClosure:() throws -&gt; Void = { ... }`.<br class="">
&gt;&gt;&gt;<br class="">
&gt;&gt;&gt;<br class="">
&gt;&gt;&gt;&gt; Can a non-async closure be passed to a function expecting a async closure?<br class="">
&gt;&gt;&gt;<br class="">
&gt;&gt;&gt; Yes. Like we can pass `() -&gt; Void` to a function expecting a throwing<br class="">
&gt;&gt;&gt; closure `() throws -&gt; Void`.<br class="">
&gt;&gt;&gt;<br class="">
&gt;&gt;&gt; It is possible because `(Foo) throws -&gt; Bar` is a supertype of `(Foo)<br class="">
&gt;&gt;&gt; -&gt; Bar`. `(Foo) async -&gt; Bar` is a supertype of `(Foo) -&gt; Bar` in the<br class="">
&gt;&gt;&gt; same way.<br class="">
&gt;&gt;&gt;<br class="">
&gt;&gt;&gt; To treat an async function as a sync function is legal. It is similar<br class="">
&gt;&gt;&gt; to make a `Promise` by `Promise(value)` which is completed<br class="">
&gt;&gt;&gt; immediately.<br class="">
&gt;&gt;&gt;<br class="">
&gt;&gt;&gt;<br class="">
&gt;&gt;&gt;&gt; Can an async closure be passed to a function expecting a non-async closure?<br class="">
&gt;&gt;&gt;<br class="">
&gt;&gt;&gt; No. `() -&gt; Void` is a subtype of `() async -&gt; Void`. It is same as<br class="">
&gt;&gt;&gt; passing `() throws -&gt; Void` to a function expecting `() -&gt; Void` is<br class="">
&gt;&gt;&gt; not allowed.<br class="">
&gt;&gt;<br class="">
&gt;&gt; But why not? Just asserting that it must work the same as throws<br class="">
&gt;&gt; is not a convincing argument. You have to justify why it must work<br class="">
&gt;&gt; that way. I think there is good reason to allow it, which I have described.<br class="">
&gt;&gt; What reason is there to disallow it?<br class="">
&gt;<br class="">
&gt; `() async -&gt; Void` needs to be called with `await` because it prevents<br class="">
&gt; us from forgetting handling asynchronous operations.<br class="">
&gt;<br class="">
&gt; If we use callbacks to handle asynchronous operations, it is shown to<br class="">
&gt; us by a compiler as a compilation error.<br class="">
&gt;<br class="">
&gt; ```<br class="">
&gt; func fooAsync(_ handler: () -&gt; Void) -&gt; Void { ... }<br class="">
&gt;<br class="">
&gt; fooAsync() // compilation error<br class="">
&gt;<br class="">
&gt; fooAsync {<br class="">
&gt;&nbsp; &nbsp;// handles a completion event here<br class="">
&gt; }<br class="">
&gt; ```<br class="">
&gt;<br class="">
&gt; With proposed `async/await`, it is realized similarly like below.<br class="">
&gt;<br class="">
&gt; ```<br class="">
&gt; func fooAsync() async -&gt; Void { ... }<br class="">
&gt;<br class="">
&gt; fooAsync() // compilation error<br class="">
&gt;<br class="">
&gt; await fooAsync()<br class="">
&gt; // handles a completion event here<br class="">
&gt; ```<br class="">
&gt;<br class="">
&gt; However, if async void functions work like `beginAsync`, we can easily<br class="">
&gt; forget it and it can cause unexpected behaviors.<br class="">
&gt;<br class="">
&gt; ```<br class="">
&gt; func fooAsync() async -&gt; Void { ... }<br class="">
&gt;<br class="">
&gt; fooAsync() // OK<br class="">
&gt; // hard to know this line is executed asynchronously<br class="">
&gt; ```<br class="">
&gt;<br class="">
&gt; Readability also suffers seriously. If we don't know `bar` in the<br class="">
&gt; following code is a async function, it is impossible to expect lines<br class="">
&gt; after `baz()` are executed asynchronously.<br class="">
&gt;<br class="">
&gt; ```<br class="">
&gt; foo()<br class="">
&gt; bar()<br class="">
&gt; baz()<br class="">
&gt; qux()<br class="">
&gt; ```<br class="">
&gt;<br class="">
&gt;<br class="">
&gt;&gt;&gt;&gt; It’s weird to me that we would allow you to have async void closures but not async void functions<br class="">
&gt;&gt;&gt;<br class="">
&gt;&gt;&gt; I am not sure what you mean. "async void closures" and "async void<br class="">
&gt;&gt;&gt; functions" have a same type. Following two are almost same.<br class="">
&gt;&gt;&gt;<br class="">
&gt;&gt;&gt; ```<br class="">
&gt;&gt;&gt; func foo() async -&gt; Void { ... }<br class="">
&gt;&gt;&gt; let foo: () async -&gt; Void = { ... }<br class="">
&gt;&gt;&gt; ```<br class="">
&gt;&gt;<br class="">
&gt;&gt; What started this thread is my suggestion that you should be able to write<br class="">
&gt;&gt; an async void function. The current proposal doesn’t allow that. That’s why<br class="">
&gt;&gt; you have to use beginAsync.<br class="">
&gt;&gt;<br class="">
&gt;&gt; I don’t think that makes sense. It sounds like you also think that would be strange,<br class="">
&gt;&gt; hence your assumption that you could.<br class="">
&gt;<br class="">
&gt; By the reasons I wrote above, we need `await` even for async void<br class="">
&gt; functions for checks by compilers. Then it is required to provide a<br class="">
&gt; way to write entry points of async functions. That is `beginAsync`.<br class="">
&gt;<br class="">
&gt; --<br class="">
&gt; Yuta<br class="">
&gt; ______________________________<wbr class="">_________________<br class="">
&gt; swift-evolution mailing list<br class="">
&gt; <a href="mailto:swift-evolution@swift.org" 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/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a><br class="">
______________________________<wbr class="">_________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" 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/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a><br class="">
</div></div></blockquote></div><br class=""></div></div></div>
</div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></body></html>