<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">From what I understand, the C# and Swift designs are different:</div><div class=""><br class=""></div><div class="">- C# async functions immediately return a task which can be enqueued to complete the work (including selecting which queue for UI cases, etc). Tasks have callback behavior attached to them.</div><div class=""><br class=""></div><div class="">- Swift async functions immediately enqueue to do work along with a callback function to be executed once work finishes. There is no first-class representation of a Future or the like, at least by default (a callback function could be promoted to a future). There is no support for selecting which queue work or the callback runs on (although your callback could immediately enqueue work on the appropriate thread, but this does increase latency in busy systems)</div><div class=""><br class=""></div><div class="">Assuming I got the above all correct there is no async Task vs async Void in swift, because a function which dispatches work to a queue without taking a callback just returns void. Those functions aren’t “async” at all, you can call them normally to dispatch work just as easily as you could call them within an async block, and they would have the same behavior. They also can’t be “awaited”, because there is no callback mechanism to tell when the work completes.</div><div class=""><br class=""></div><div class="">Thats not to say I wouldn’t prefer the Task-type design, but it isn’t how most of the legacy asynchronous code is written to work (and would have some issues with GCD, since you can’t discover your current queue in order to enqueue more work there by default)</div><div class=""><br class=""></div><div class="">// Function which asynchronously dispatches work, without triggering any callback. If it throws, the error represents a synchronous issue (e.g. bad parameters or state)</div><div class=""><br class=""></div><div class="">func doWorkBlindly();</div><div class=""><br class=""></div><div class="">// Function which asynchronously dispatches work, returning a callback without data but possibly indicating an error</div><div class="">func doWorkExceptionally() async -&gt; Void;</div><div class=""><br class=""></div><div class="">// Function which asynchronously dispatches work ,returning data and possibly an error</div><div class="">func doValuableWork() async -&gt; Data;</div><div class=""><br class=""></div><div class="">// works fine</div><div class="">doWorkBlindly()</div><div class="">beginAsync {</div><div class="">&nbsp; &nbsp; // has the same behavior as above</div><div class="">&nbsp; &nbsp; doWorkBlindly()</div><div class="">&nbsp; &nbsp; do {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; // can only be called within an async block</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; await doWorkExceptionally()</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; let result = await doValuableWork()</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; catch {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;fatalError()</div><div class="">&nbsp; &nbsp; }</div><div class="">}</div><div class=""><br class=""></div><div class="">-DW</div><div class=""><br class=""></div><br class=""><div><blockquote type="cite" class=""><div class="">On Nov 12, 2017, at 10:56 AM, Xiaodi Wu 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 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>
_______________________________________________<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></blockquote></div><br class=""></body></html>