<div dir="ltr"><div class="gmail_quote"><div dir="ltr">Tanks Jonathan,</div><div dir="ltr"><br></div><div dir="ltr">As you may already know, I am a great advocate of this feature. I will not repeat my explanations and examples that I gave in the other threads. But I think you got the idea right. Even without any kind of optimization, I believe there is a clear gain in this approach.<br></div><div dir="ltr"><br></div><div dir="ltr">But I think you got the idea right. Even without any kind of optimization, I believe there is a clear gain.<br></div><div dir="ltr"><br></div><div dir="ltr">It is extremely naive to believe that people do not need a basic parallelism already in the first version. 100% of people will have to look for third-party libraries, or create their custom versions on top of async / await already on the first day. Batch two (or more) things to do in the same function is a pretty common pattern.</div><div dir="ltr"><br></div><div dir="ltr"><pre style="box-sizing:border-box;font-family:SFMono-Regular,Consolas,&quot;Liberation Mono&quot;,Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(246,248,250);border-radius:3px;word-break:normal;color:rgb(36,41,46)"><span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">processImageData1a</span>() async <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-&gt;</span> Image {
  <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> dataResource  <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> async <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">loadWebResource</span>(<span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(3,47,98)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">&quot;</span>dataprofile.txt<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">&quot;</span></span>)
  <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> imageResource <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> async <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">loadWebResource</span>(<span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(3,47,98)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">&quot;</span>imagedata.dat<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">&quot;</span></span>)
  
  <span class="inbox-inbox-pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"><span class="inbox-inbox-pl-c" style="box-sizing:border-box">//</span> ... other stuff can go here to cover load latency...</span>
<span class="inbox-inbox-pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"></span>  
  <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> imageTmp    <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> await <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">decodeImage</span>(dataResource, imageResource) // compiler error if await is not present.
  <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> imageResult <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> await <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">dewarpAndCleanupImage</span>(imageTmp)
  <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">return</span> imageResult
}</pre></div><div dir="ltr"><br></div><div>If this (or something like that) is not implemented, people will create several versions to solve the same problem, so that later (Swift 6?) will be solved (because people want this), and we will live with several bad codes to maintain.</div><div><br></div><div dir="ltr">Since I do not think we should encourage building bad coding standards to solve simple problems (and I&#39;ve seen very bad few examples of this right here), I think we should sort this out soon enough. Even without obvious optimizations in the first version.<br></div><div dir="ltr"><br></div><div>Future/Promises is another talk! Involve a lot of other concepts, and also will be a shame to need the Future/Promises to solve this problem, because this is something that we actually can do using GCD only, without involve any other type/controlling mechanism. And also, can help build better Future/Promises too.</div><div><br></div><div><br></div><div><br></div><div dir="ltr">Em seg, 4 de set de 2017 às 02:37, Jonathan Hull via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; escreveu:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">I think we need to consider both the original proposal on its own, and also together with other potential proposals (including deferring ‘async’ and futures). We don’t need to have them fully spelled out, but I think the other proposals will help inform us where the sharp edges of await/async are.  That was my original point on this thread.<div><br></div><div>I keep seeing “Let’s wait to consider X until after async/await” and I am saying “Let’s consider how X would affect the async/await proposal”.  Better to figure out any design issues and back-propagation now than after we have baked things in.</div><div><br></div><div>Thanks,</div><div>Jon</div></div><div style="word-wrap:break-word"><div><br><div><blockquote type="cite"><div>On Sep 3, 2017, at 10:16 PM, BJ Homer &lt;<a href="mailto:bjhomer@gmail.com" target="_blank">bjhomer@gmail.com</a>&gt; wrote:</div><br class="m_743790097984045461m_-3750606154095181661Apple-interchange-newline"><div><div dir="auto"><div>Okay, that&#39;s an interesting proposal. I&#39;m not qualified to judge how big of a win the compiler optimizations would be there; I&#39;m a little skeptical, but I admit a lack of expertise there. It seems like it&#39;s not essential to the core &#39;async/await&#39; proposal, though; it could be added later with no source breakage, and in the meantime we can accomplish most of the same behavior through an explicit Future type. I think it makes more sense to consider the base proposal before adding more complexity to it.</div><div><br>-BJ</div><div><br>On Sep 3, 2017, at 10:15 PM, Jonathan Hull &lt;<a href="mailto:jhull@gbis.com" target="_blank">jhull@gbis.com</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><br><div><blockquote type="cite"><div>On Sep 3, 2017, at 7:35 PM, BJ Homer &lt;<a href="mailto:bjhomer@gmail.com" target="_blank">bjhomer@gmail.com</a>&gt; wrote:</div><br class="m_743790097984045461m_-3750606154095181661Apple-interchange-newline"><div><div dir="auto"><div>Jonathan,</div><div><br></div><div>You&#39;ve mentioned the desire to have &#39;async&#39; defer calling &#39;await&#39;, but I haven&#39;t seen a detailed design yet. </div></div></div></blockquote><div>Oh, we discussed it awhile back on a few other threads.  I am happy to help write up a more formal/detailed design if there is enough interest...</div><br><blockquote type="cite"><div><div dir="auto"><div>For example, is the following code valid?</div><div><br></div><div></div><div>  let image = async fetchImage()</div><div><div><span style="background-color:rgba(255,255,255,0)">  let image2 = async fetchImage()</span></div><div>  let deferredThings = [image1, image2]</div></div><div><div><br></div><div>If so, what is the type of &#39;deferredThings&#39;? And how does it not count as &#39;using&#39; the values.</div></div></div></div></blockquote><div><br></div>No this code is not valid.  You would need to ‘await’ both image 1 &amp; 2 before they could be put in an array or transferred to another variable. You could combine the ‘await’s though (similar to try):</div><div><br></div><div><div dir="auto"><div><span class="m_743790097984045461m_-3750606154095181661Apple-tab-span" style="white-space:pre-wrap">        </span>let image = async fetchImage()</div><div><span style="background-color:rgba(255,255,255,0)"><span class="m_743790097984045461m_-3750606154095181661Apple-tab-span" style="white-space:pre-wrap">        </span>let image2 = async fetchImage()</span></div><div><span class="m_743790097984045461m_-3750606154095181661Apple-tab-span" style="white-space:pre-wrap">        </span>let deferredThings = await [image1, image2]</div><div><br></div><div><br></div><div>Note: You can return something which is deferred from an async function without awaiting though...</div></div><div><br></div><br><blockquote type="cite"><div><div dir="auto"><div><div>If the above code is not valid, how is this situation better than the suggested use of a Future type to allow concurrent async requests?</div><div><br></div><div><div><span style="background-color:rgba(255,255,255,0)">  let future1 = Future { await fetchImage() }</span></div><div><div><span style="background-color:rgba(255,255,255,0)">  let future2 = Future { await fetchImage() }</span></div><div><span style="background-color:rgba(255,255,255,0)">  let deferredThings = [future1, future2]</span></div><div><span style="background-color:rgba(255,255,255,0)"><br></span></div><div><span style="background-color:rgba(255,255,255,0)">Note that in this example, &#39;deferredThings&#39; has a concrete type, and we can inspect its values.</span></div></div></div></div></div></div></blockquote><div><br></div><div>It isn’t meant to be used instead of Futures (though you may not need to reach for them as often), it is a much lower-level construct which would be used as a building block for things like futures (and other concurrency constructs).</div><div><br></div><div>Because there is no way for the programmer to get at the thing being ‘await’ed (or any representation of it) without awaiting on it, and it can’t escape the context, it gives the compiler some extra guarantees that it can use to optimize things behind the scenes. Even if the compiler just ends up creating a future behind the scenes, that implementation is completely hidden to the programmer, and can be updated/changed at any time by the compiler team without involving evolution.</div><div><br></div><div>Let’s say at some point down the road as part of the actor work, the compiler ends up getting some visibility into how actor queues will be coalesced… Then it can use that knowledge to reorganize the code above to be more efficient.  For example, if it knows that the part of the calls to fetchImage() will be serialized by an actor, it can just make that part synchronous and avoid the asynchronous overhead.  If we had baked in everything at the low-level to use future objects, we wouldn’t be able to make that optimization.</div><div><br></div><div>There are 2 big results from this:</div><div><br></div><div>1) It gives us the ability to easily start several things behind the scenes and then await the group of them finishing</div><div><br></div><div>2) Our implementation of Futures (and other constructs) can potentially take advantage of the compiler optimizations by using this beneath the hood.</div><div><br></div><div><br></div><div>The first point is huge for me. This is an extremely common thing to want in real-world code, but it usually requires a bunch of complex (sometimes error-prone) machinery to actually pull off. There is often wasted overhead as well.  I like that I can do it here in a very natural and lightweight way.  (Futures also simplify this problem a great deal, but I wouldn’t really call them lightweight). </div><div><br></div><br><blockquote type="cite"><div dir="auto"><div><div><div><div>You keep bringing up this suggestion, so I must be missing something, but it seems to me that your suggestion is covered by Futures. Why is calling with &#39;async&#39; better?</div></div></div></div></div></blockquote><div><br></div><div>As I said above, I think this will help our Futures be much more efficient when we build them, but there are also some advantages of having this as an option and not just using Futures for everything.</div><div><br></div><div>Mainly, futures require a different return type, and they require boxing/unboxing.  To chain futures, each link in the chain has to be future-aware… and each link can only be used with futures (i.e. the return type is Future&lt;MyType&gt;).  There are a lot of cases where I am boxing just to unbox and re-box.  Most of that is fine as long as the framework was built with it in mind, but it doesn’t work as well if I want to add the functionality post-hoc.</div><div><br></div><div>With ‘async’ being used to defer ‘await’, it just works on any function which can be awaited.  Further, it can be chained naturally through any number of async functions.  I showed this in another thread, but if you think through what happens when you return something which still needs to be awaited, you see that that state is naturally passed along with it (the function was either called with ‘await’ or ‘async’, and thus the return value is either awaited on, or the result picks up the compiler marking from ‘async’ showing it still needs to be awaited).  Because there is no (visible) boxing, you don’t have to worry about monads, etc…</div><div><br></div><div>It basically nests in the same way that try/throws nests, and we already have to do that for async/await anyway… so it is a lot of win for very little additional complexity (at least on the usage side).</div><div><br></div><div>Thanks,</div><div>Jon</div><div><br></div><div><br></div><br><blockquote type="cite"><div dir="auto"><div>-BJ</div><div><br>On Sep 3, 2017, at 6:01 PM, Jonathan Hull via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><br><div><blockquote type="cite"><div>On Sep 3, 2017, at 9:04 AM, Chris Lattner via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><div><div style="word-wrap:break-word"><div><blockquote type="cite"><div>On Sep 3, 2017, at 4:00 AM, David Hart &lt;<a href="mailto:david@hartbit.com" target="_blank">david@hartbit.com</a>&gt; wrote:</div><div><div class="m_743790097984045461m_-3750606154095181661Singleton" style="word-wrap:break-word"><div><blockquote type="cite" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div><div>Please don’t read too much into the beginAsync API.  It is merely a strawman, and intended to be a low-level API that higher level abstractions (like a decent futures API) can be built on top of.  I think it is important to have some sort of primitive low-level API that is independent of higher level abstractions like Futures.<br><br>This is all a way of saying “yes, having something like you propose makes sense” but that it should be part of the Futures API, which is outside the scope of the async/await proposal.<br></div></div></blockquote><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">But it would be nice for all high-level APIs that conform to a<span class="m_743790097984045461m_-3750606154095181661Apple-converted-space"> </span><b>Awaitable</b><span class="m_743790097984045461m_-3750606154095181661Apple-converted-space"> </span>protocol to be used with<span class="m_743790097984045461m_-3750606154095181661Apple-converted-space"> </span><b>await</b><span class="m_743790097984045461m_-3750606154095181661Apple-converted-space"> </span>without having to reach for a<span class="m_743790097984045461m_-3750606154095181661Apple-converted-space"> </span><b>get</b><span class="m_743790097984045461m_-3750606154095181661Apple-converted-space"> </span>property or something similar everytime.</div></div></div></div></blockquote><br></div><div>The futures API that is outlined in the proposal is just an example, it isn’t a concrete pitch for a specific API.  There are a bunch of improvements that can (and should) be made to it, it is just that a futures API should be the subject of a follow-on proposal to the basic async/await mechanics.</div></div></div></blockquote><br></div><div>Would it be possible to have the manifesto be a series of proposals then?  I really think it is important for us to look at how all of these things fit together.  I agree that async/await should come first, but looking at how concrete things like Futures would work may help to inform the design of async/await.  We should do the back-propigation in our design before anything is locked in...</div><div><br></div><div>The thing I would most like to see as a quick follow-on to async/await is the ability to use the ‘async’ keyword to defer ‘await’. This feels very natural, is highly optimizable by the compiler, and it allows for a lot of very common use-cases which are not covered well by pure async/await.  I think it would have a large impact on the eventual design/implementation of futures (and at least some impact on the design of async/await).</div><br><div>Thanks,</div><div>Jon</div></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></div></blockquote></div><br></div></blockquote></div></div></blockquote></div><br></div></div>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</blockquote></div></div>