<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto">I understand. But it’s quite problematic to have to write all Future returning functions with Future inputs just to be able to support parallel computations. It’s not how futures are using in C# and JavaScript.<br><div><br>On 30 Aug 2017, at 03:02, Howard Lovatt &lt;<a href="mailto:howard.lovatt@gmail.com">howard.lovatt@gmail.com</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><div dir="ltr">@David,<div><br></div><div>The signatures would be:</div><div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><br></div></blockquote></div><div><div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">func processImage(_ image: Future&lt;Image&gt;) -&gt; Future&lt;Image&gt;</blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">func translate(_ text: Future&lt;String&gt;) -&gt; Future&lt;Image&gt;</blockquote></div></div><div><br></div><div>Inside `processImage` and `translate` you would `get` the values at the point were needed so that downloadImage and downloadText run in parallel (which is highly desirable).</div><div><br></div></div><div class="gmail_extra"><br clear="all"><div><div class="gmail_signature" data-smartmail="gmail_signature">&nbsp; -- Howard.<br></div></div>
<br><div class="gmail_quote">On 30 August 2017 at 07:21, David Hart <span dir="ltr">&lt;<a href="mailto:david@hartbit.com" target="_blank">david@hartbit.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>I don’t think the examples are 100% equivalent. In your version with the Future library,&nbsp;<b>preprocessImage</b> and&nbsp;<b>translate</b> need to accept futures as argument, correct? That’s more restrictive than in my example code where async/await specifically provide sugar over <b>then</b>. Plus I don’t understand why you mention that the Future version handles errors when async/await also plays very nicely with errors.</div><div><div class="h5"><div><br></div><div><blockquote type="cite"><div>On 29 Aug 2017, at 10:22, Howard Lovatt &lt;<a href="mailto:howard.lovatt@gmail.com" target="_blank">howard.lovatt@gmail.com</a>&gt; wrote:</div><br class="m_1881708220171369895Apple-interchange-newline"><div><div dir="ltr">@David,<div><br></div><div>Using the `Future` library based on GCD that I have previously posted your example would be:</div><div><br></div><div><pre style="white-space:pre-wrap;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;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="m_1881708220171369895gmail-m_7892036109698415928pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> image <span class="m_1881708220171369895gmail-m_7892036109698415928pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> <span class="m_1881708220171369895gmail-m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">preprocessImage</span>(<span class="m_1881708220171369895gmail-m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">downloadImage</span>(<wbr>)) // These first two lines run in parallel
<span class="m_1881708220171369895gmail-m_7892036109698415928pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> text <span class="m_1881708220171369895gmail-m_7892036109698415928pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> <span class="m_1881708220171369895gmail-m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">translate</span>(<span class="m_1881708220171369895gmail-m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">downloadText</span>())
<span class="m_1881708220171369895gmail-m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">render</span>(<span class="m_1881708220171369895gmail-m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">image</span>: image.get ?? defaultImage, <span class="m_1881708220171369895gmail-m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">text</span>: text.get ?? defaultText)</pre></div><div><br></div><div>The main difference, and I would argue an improvement, is that the `Future` version handles errors.</div><div><br></div><div>So what advantage does async/await have over a `Future` library we can write today?</div><div><br></div></div><div class="gmail_extra"><br clear="all"><div><div class="m_1881708220171369895gmail_signature" data-smartmail="gmail_signature">&nbsp; -- Howard.<br></div></div>
<br><div class="gmail_quote">On 29 August 2017 at 15:28, David Hart via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><br><div><span><blockquote type="cite"><div>On 29 Aug 2017, at 02:22, Xiaodi Wu via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_1881708220171369895m_7892036109698415928Apple-interchange-newline"><div><div>On Mon, Aug 28, 2017 at 16:10 Adam Kemp via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space">I know what the proposal said. I’m making a case that there is value in doing it differently.<div><br></div><div>The composability of futures is valuable. Mixing and matching async/await with futures is also valuable. The queue-returning behavior that you can get from futures is also valuable, and building async/await on top of futures means async/await can get that for free.</div></div></blockquote><div dir="auto"><br></div><div dir="auto">Why couldn't you mix and match async/await and futures and get the queue-return behavior of futures if futures are built on top of async/await instead off the other way around?</div></div></div></div></blockquote><div><br></div></span><div>We could, but the syntax is much worse. Contrast:</div><div><br></div><div><b>async/await built on top of Futures</b></div><div><b><br></b></div><div><pre style="box-sizing:border-box;font-family:SFMono-Regular,Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.600000381469727px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(246,248,250);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal;color:rgb(36,41,46)"><span class="m_1881708220171369895m_7892036109698415928pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> image <span class="m_1881708220171369895m_7892036109698415928pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> <span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">preprocessImage</span>(<span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">downloadImage</span>(<wbr>))
<span class="m_1881708220171369895m_7892036109698415928pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> text <span class="m_1881708220171369895m_7892036109698415928pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> <span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">translate</span>(<span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">downloadText</span>())
await <span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">render</span>(<span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">image</span>: image, <span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">text</span>: text)</pre></div><div><br></div><div><div><b>Futures built on top of async/await</b></div><div><b><br></b></div><div><pre style="box-sizing:border-box;font-family:SFMono-Regular,Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.600000381469727px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(246,248,250);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal;color:rgb(36,41,46)"><span class="m_1881708220171369895m_7892036109698415928pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> image <span class="m_1881708220171369895m_7892036109698415928pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> <span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">Future</span>(downloadImage).<span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">then</span>({ <span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">preprocessImage</span>(<span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">$0</span>) })
<span class="m_1881708220171369895m_7892036109698415928pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> text <span class="m_1881708220171369895m_7892036109698415928pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> <span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">Future</span>(downloadText).<span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">then</span>({ <span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">translate</span>(<span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">$0</span>) })
await <span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">render</span>(<span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">image</span>: image.<span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">get</span>(), <span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">text</span>: text.<span class="m_1881708220171369895m_7892036109698415928pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">get</span>())</pre></div></div><div><div class="m_1881708220171369895h5"><br><blockquote type="cite"><div><div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><div></div></div></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><div>Maybe you don’t value those things, which is fine. But I do, and maybe other people do too. That’s why we’re having a discussion about it.</div><div><div><br></div><div>It can also be valuable having a minimal implementation, but we have to acknowledge that it comes with a downside as well. The problem with doing a minimal implementation is that you can be stuck with the consequences for a long time. I want to make sure that we’re not stuck with the consequences of a minimal implementation that doesn’t adequately address the problems that async/await should be addressing. I’d hate for Swift to get an async/await that is so weak that it has to be augmented by tedious boilerplate code before it’s useful.</div></div></div><div style="word-wrap:break-word;line-break:after-white-space"><div><div><br><div><br><blockquote type="cite"><div>On Aug 28, 2017, at 1:54 PM, Wallacy &lt;<a href="mailto:wallacyf@gmail.com" target="_blank">wallacyf@gmail.com</a>&gt; wrote:</div><br class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611Apple-interchange-newline"><div><div>We don't need to this now!<div><br></div><div>Again: (Using proposal words)</div><div><br></div><div>"<span style="color:rgb(36,41,46);font-family:-apple-system,BlinkMacSystemFont,&quot;Segoe UI&quot;,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;,&quot;Segoe UI Symbol&quot;;font-size:16px">It is important to understand that this is proposing compiler support that is completely concurrency runtime-agnostic. This proposal does not include a new runtime model (like "actors") - it works just as well with GCD as with pthreads or another API. Furthermore, unlike designs in other languages, it is independent of specific coordination mechanisms, such as futures or channels, allowing these to be built as library feature</span>"</div><div><br></div><div>and</div><div><br></div><div>"<span style="color:rgb(36,41,46);font-family:-apple-system,BlinkMacSystemFont,&quot;Segoe UI&quot;,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;,&quot;Segoe UI Symbol&quot;;font-size:16px">This proposal does not formally propose a&nbsp;</span><code style="box-sizing:border-box;font-family:SFMono-Regular,Consolas,&quot;Liberation Mono&quot;,Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;background-color:rgba(27,31,35,0.05);border-radius:3px;color:rgb(36,41,46)">Future</code><span style="color:rgb(36,41,46);font-family:-apple-system,BlinkMacSystemFont,&quot;Segoe UI&quot;,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;,&quot;Segoe UI Symbol&quot;;font-size:16px">&nbsp;type, or any other coordination abstractions. There are many rational designs for futures, and a lot of experience working with them. On the other hand, there are also completely different coordination primitives that can be used with this coroutine design, and incorporating them into this proposal only makes it larger.</span>"</div><div><br></div><div>and</div><div><br></div><div><span style="color:rgb(36,41,46);font-family:-apple-system,BlinkMacSystemFont,&quot;Segoe UI&quot;,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;,&quot;Segoe UI Symbol&quot;;font-size:16px">We focus on task-based concurrency abstractions commonly encountered in client and server applications, particularly those that are highly event driven (e.g. responding to UI events or requests from clients). This does not attempt to be a comprehensive survey of all possible options, nor does it attempt to solve all possible problems in the space of concurrency. Instead, it outlines a single coherent design thread that can be built over the span of years to incrementally drive Swift to further greatness.</span>&nbsp;</div><div><br></div><div>and</div><div><br></div><div><span style="color:rgb(36,41,46);font-family:-apple-system,BlinkMacSystemFont,&quot;Segoe UI&quot;,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;,&quot;Segoe UI Symbol&quot;;font-size:16px">This proposal has been kept intentionally minimal, but there are many possible ways to expand this in the future.</span></div><div><br></div><div>....</div><div><br></div>The point is: No Future type is indeed proposed yet! <div><br></div><div>The proposal try to include de "minimum" required to implement a basic async/await to solve the problem created by the GCD!&nbsp;(Pyramid of doom)</div><div><br></div><div>The question is: How do you do the same using&nbsp;<span style="background-color:rgb(249,250,250);font-family:&quot;SF Mono&quot;,Menlo,monospace,&quot;SF Pro Icons&quot;;font-size:15px;letter-spacing:-0.405px;white-space:pre-wrap">dispatch_async ?</span> dispatch_async also does not return nothing to do what you are intentend do do!</div><div><br></div><div>Algo, by Swift 5 manifesto, there's no compromise to make a "complete" concurrency model by this time!<br></div><div><br></div><div>My intention is only make parity to dispatch_async, but also make the ground free to make more complex implementation like Futures in another round on top of this one.</div><div><br></div><div>This 'async T' can be a real type in the future? Maybe will... But doesn't matter now! Now we only need to is some kind of type which need to be unwrapped using await before use. Maybe this intermediary/virtual type can be a real thing and gain some abilities at some point! Maybe a full Future type, why not?</div></div><br><div class="gmail_quote"><div>Em seg, 28 de ago de 2017 às 17:33, Adam Kemp &lt;<a href="mailto:adam.kemp@apple.com" target="_blank">adam.kemp@apple.com</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;line-break:after-white-space">How would these anonymous types get composed? If I wanted to implement a function that takes a collection of futures and wait on it, how would I do that? That is, how would I implement the equivalent of C#’s Task.WhenAll and Task.WhenAny methods?<div><br></div><div>More generally, how do you pass one of these typeless futures to some other function so that we can do the waiting there?</div></div><div style="word-wrap:break-word;line-break:after-white-space"><div><br><div><br><blockquote type="cite"><div>On Aug 28, 2017, at 1:23 PM, Wallacy &lt;<a href="mailto:wallacyf@gmail.com" target="_blank">wallacyf@gmail.com</a>&gt; wrote:</div><br class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497Apple-interchange-newline"><div><div><div>And that's why I (and others) are suggesting:<br></div><div><br></div><div><div style="color:rgb(33,33,33);font-size:13px">func processImageData1a() async -&gt; Image {</div><div><span style="color:rgb(33,33,33);font-size:13px">&nbsp; let dataResource &nbsp;= async loadWebResource("dataprofile.t<wbr>xt") //&nbsp;</span><font color="#212121">No future type here... Just another way to call dispatch_async under the hood.</font></div><div style="color:rgb(33,33,33);font-size:13px">&nbsp; let imageResource = async&nbsp;loadWebResource("imageda<wbr>ta.dat")</div><div style="color:rgb(33,33,33);font-size:13px">&nbsp;&nbsp;</div><div style="color:rgb(33,33,33);font-size:13px">&nbsp; // ... other stuff can go here to cover load latency...</div><div style="color:rgb(33,33,33);font-size:13px">&nbsp;&nbsp;</div><div style="color:rgb(33,33,33);font-size:13px">&nbsp; let imageTmp &nbsp; &nbsp;= await decodeImage(dataResource, imageResource) // Compiles force await call here...</div><div style="color:rgb(33,33,33);font-size:13px">&nbsp; let imageResult = await dewarpAndCleanupImage(imageTmp<wbr>)</div><div style="color:rgb(33,33,33);font-size:13px">&nbsp; return imageResult</div><div style="color:rgb(33,33,33);font-size:13px">}</div><div style="color:rgb(33,33,33);font-size:13px"><br></div><div><font color="#212121">And now we gain all advantages of async/await again without to handle with one more type.</font><br></div><br><div class="gmail_quote"><div>Em seg, 28 de ago de 2017 às 17:07, Adam Kemp 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;line-break:after-white-space">I think the biggest tradeoff is clearer when you look at the examples from the proposal where futures are built on top of async/await:<div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div>func processImageData1a() async -&gt; Image {</div><div>&nbsp; let dataResource &nbsp;= Future { await loadWebResource("dataprofile.t<wbr>xt") }</div><div>&nbsp; let imageResource = Future { await loadWebResource("imagedata.dat<wbr>") }</div><div>&nbsp;&nbsp;</div><div>&nbsp; // ... other stuff can go here to cover load latency...</div><div>&nbsp;&nbsp;</div><div>&nbsp; let imageTmp &nbsp; &nbsp;= await decodeImage(dataResource.get()<wbr>, imageResource.get())</div><div>&nbsp; let imageResult = await dewarpAndCleanupImage(imageTmp<wbr>)</div><div>&nbsp; return imageResult</div><div>}</div></div></blockquote><div><br></div>With this approach you have to wrap each call site to create a future. Compare to this:<div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div>func processImageData1a() -&gt; Future&lt;Image&gt; {</div><div>&nbsp; let dataResourceFuture &nbsp;= loadWebResource("dataprofile.t<wbr>xt”);</div><div>&nbsp; let imageResourceFuture = loadWebResource("imagedata.dat<wbr>”);</div><div>&nbsp;&nbsp;</div><div>&nbsp; // ... other stuff can go here to cover load latency...</div><div>&nbsp;&nbsp;</div><div>&nbsp; let imageTmp &nbsp; &nbsp;= await decodeImage(await dataResourceFuture, await imageResourceFuture)</div><div>&nbsp; let imageResult = await dewarpAndCleanupImage(imageTmp<wbr>)</div><div>&nbsp; return imageResult</div><div>}</div></div></blockquote><div><br></div>Here, not only are the explicit wrappers gone, but this function itself can be used with either await or as a future. You get both options with one implementation.</div><div><br></div><div>As I’ve mentioned before, C#’s implementation is not tied to any one particular futures implementation. The Task type is commonly used, but async/await does not directly depend on Task. Instead it works with any return type that meets certain requirements (detailed here:&nbsp;<a href="https://blogs.msdn.microsoft.com/pfxteam/2011/01/13/await-anything/" target="_blank">https://blogs.msdn.micro<wbr>soft.com/pfxteam/2011/01/13/<wbr>await-anything/</a>). Swift could do this using a protocol, which can be retroactively applied using an extension.</div><div><br></div><div>Obviously for this to be useful we would need some kind of existing future implementation, but at least we wouldn’t be tied to any particular one. That would mean library maintainers who have already been using their own futures implementations could quickly adopt async/await in their code without having to rewrite their futures library or throw wrappers around every usage of async/await. They could just adopt a protocol (using an extension, even) and get async/await support for free.</div><div><br></div><div>The downside is that this feature would be specific to the async/await use case rather than a generic coroutine implementation (i.e., there would have to be a separate compiler transform for yield return). It’s not clear to me why it should be a goal to have just one generic coroutine feature. The real-world usages of async/await and yield return are different enough that I’m not convinced we could have a single compiler feature that meets the needs of both cleanly.</div></div><div style="word-wrap:break-word;line-break:after-white-space"><div><div><div><div><div><div><br><blockquote type="cite"><div>On Aug 27, 2017, at 7:35 PM, Florent Vilmart &lt;<a href="mailto:florent@flovilmart.com" target="_blank">florent@flovilmart.com</a>&gt; wrote:</div><br class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259Apple-interchange-newline"><div>



<div>
<div name="messageBodySection">Adam, you’re completely right, languages as c# and JS have been through the path before, (callback, Promises , async/await) I believe Chris’s goal it to avoid building a promise implementation and go straight to a coroutines model, which is more deeply integrated with the compiler. I don’t see a particular trade off, pursuing that route, and the main benefit is that coroutines can power any asynchronous metaphor (Signals, Streams, Futures, Promises etc...) which is not true of Futures so i would tend to think that for the long run, and to maximize usability, async/await/yield would probably be the way to go.</div>
<div name="messageReplySection"><br>
On Aug 27, 2017, 22:22 -0400, Adam Kemp &lt;<a href="mailto:adam.kemp@apple.com" target="_blank">adam.kemp@apple.com</a>&gt;, wrote:<br>
<blockquote type="cite">
<div>As has been explained, futures can be built on top of async/await (or the other way around). You can have the best of both worlds. We are not losing anything by having this feature. It would be a huge improvement to have this as an option.&nbsp;</div>
<div><br></div>
<div>However, using futures correctly requires more nested closures than you have shown in your examples to avoid blocking any threads. That's why you're not seeing the advantage to async/await. You're comparing examples that have very different behaviors.</div>
<div><br></div>
<div>That said, I have also expressed my opinion that it is better to build async/await on top of futures rather than the other way around. I believe it is more powerful and cleaner to make async/await work with any arbitrary future type (via a protocol). The alternative (building futures on top of async/await) requires more code when the two are mixed. I very much prefer how it's done in C#, where you can freely mix the two models without having to resort to ad-hoc wrappers, and you can use async/await with any futures implementation you might already be using.</div>
<div><br></div>
<div>I really think we should be having more discussion about the tradeoffs between those two approaches, and I'm concerned that some of the opinions about how C# does it are not based on a clear and accurate understanding of how it actually works in that language.&nbsp;</div>
<div><br>
--
<div>Adam Kemp</div>
</div>
<div><br>
On Aug 27, 2017, at 6:02 PM, Howard Lovatt &lt;<a href="mailto:howard.lovatt@gmail.com" target="_blank">howard.lovatt@gmail.com</a>&gt; wrote:<br>
<br></div>
<blockquote type="cite">
<div>
<div>The async/await is very similar to the proposed Future (as I posed earlier) with regard to completion-handler code, they both re-write the imported completion-handler function using a closure, the relevant sentence from the Async Proposal is:
<div><br></div>
<blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">"Under the hood, the compiler rewrites this code using nested closures ..."<br></blockquote>
<br>
<div>Unlike the proposed future code the async code is not naturally parallel, in the running example the following lines from the async code are run in series, i.e. await blocks:</div>
<div><br></div>
<div>
<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="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> dataResource  <span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> await <span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">loadWebResource</span>(<span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-s" style="box-sizing:border-box;color:rgb(3,47,98)"><span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-pds" style="box-sizing:border-box">"</span>dataprofile.t<wbr>xt<span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-pds" style="box-sizing:border-box">"</span></span>)
  <span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> imageResource <span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> await <span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">loadWebResource</span>(<span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-s" style="box-sizing:border-box;color:rgb(3,47,98)"><span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-pds" style="box-sizing:border-box">"</span>imagedata.dat<span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-pds" style="box-sizing:border-box"><wbr>"</span></span>)
</pre></div>
<div>The equivalent lines using the proposed Future:</div>
<div>
<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="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> dataResource  <span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> <span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">loadWebResource</span>(<span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-s" style="box-sizing:border-box;color:rgb(3,47,98)"><span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-pds" style="box-sizing:border-box">"</span>dataprofile.t<wbr>xt<span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-pds" style="box-sizing:border-box">"</span></span>)
  <span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> imageResource <span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> <span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">loadWebResource</span>(<span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-s" style="box-sizing:border-box;color:rgb(3,47,98)"><span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-pds" style="box-sizing:border-box">"</span>imagedata.dat<span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail-pl-pds" style="box-sizing:border-box"><wbr>"</span></span>)
</pre></div>
<div>Run in parallel and therefore are potentially faster assuming that resources, like cores and IO, are available.</div>
<div><br></div>
<div>Therefore you would be better using a Future than an async, so why provide an async unless you can make a convincing argument that it allows you to write a better future?</div>
</div>
<div class="gmail_extra"><br clear="all">
<div>
<div class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259gmail_signature" data-smartmail="gmail_signature">&nbsp; -- Howard.<br></div>
</div>
<br>
<div class="gmail_quote">On 28 August 2017 at 09:59, Adam Kemp <span>&lt;<a href="mailto:adam.kemp@apple.com" target="_blank">adam.kemp@apple.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="auto">This example still has nested closures (to create a Future), and still relies on a synchronous get method that will block a thread. Async/await does not require blocking any threads.
<div><br></div>
<div>I’m definitely a fan of futures, but this example isn’t even a good example of using futures. If you’re using a synchronous get method then you’re not using futures properly. They’re supposed to make it easy to avoid writing blocking code. This example just does the blocking call on some other thread.</div>
<div><br></div>
<div>Doing it properly would show the benefits of async/await because it would require more nesting and more complex error handling. By simplifying the code you’ve made a comparison between proper asynchronous code (with async/await) and improper asynchronous code (your example).</div>
<div><br></div>
<div>That tendency to want to just block a thread to make it easier is exactly why async/await is so valuable. You get simple code while still doing it correctly.&nbsp;</div>
<div><br>
<div id="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259m_-2707032511043914185AppleMailSignature">--
<div>Adam Kemp</div>
</div>
<div>
<div class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259h5">
<div><br>
On Aug 27, 2017, at 4:00 PM, Howard Lovatt 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>
<div>
<div dir="auto">The running example used in the white paper coded using a Future is:</div>
<div dir="auto"><br></div>
<div dir="auto"><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">func processImageData1() -&gt; Future&lt;Image&gt; {</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px">
<span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">&nbsp; &nbsp; return AsynchronousFuture { _ -&gt; Image in</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px">
<span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">&nbsp; &nbsp; &nbsp; &nbsp; let dataResource &nbsp;= loadWebResource("dataprofile.</span><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">t<wbr>xt") // dataResource and imageResource run in parallel.</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px">
<span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">&nbsp; &nbsp; &nbsp; &nbsp; let imageResource = loadWebResource("imagedata.</span><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">dat<wbr>")</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px">
<span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">&nbsp; &nbsp; &nbsp; &nbsp; let imageTmp &nbsp; &nbsp; &nbsp;= decodeImage(dataResource.get ?? Resource(path: "Default data resource or prompt user"), imageResource.get ?? Resource(path: "Default image resource or prompt user"))</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px">
<span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">&nbsp; &nbsp; &nbsp; &nbsp; let imageResult &nbsp; = &nbsp;dewarpAndCleanupImage(</span><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">imageTm<wbr>p.get ?? Image(dataPath: "Default image or prompt user", imagePath: "Default image or prompt user"))</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px">
<span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">&nbsp; &nbsp; &nbsp; &nbsp; return imageResult.get ?? Image(dataPath: "Default image or prompt user", imagePath: "Default image or prompt user")</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px">
<span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">&nbsp; &nbsp; }</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px">
<span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">}</span><br></div>
<div dir="auto"><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)"><br></span></div>
<div dir="auto">This also avoids the pyramid of doom; the pyramid is avoided by converting continuation-handlers into either a sync or future, i.e. it is the importer that eliminates the nesting by translating the code automatically.&nbsp;<br></div>
<div dir="auto"><br></div>
<div dir="auto">This example using Future also demonstrates three advantages of Future: they are naturally parallel (dataResource and imageResource lines run in parallel), they timeout automatically (get returns nil if the Future has taken too long), and if there is a failure (for any reason including timeout) it provides a method of either detecting the failure or providing a default (get returns nil on failure).&nbsp;</div>
<div dir="auto"><br></div>
<div dir="auto">There are a three of other advantages a Future has that this example doesn’t show: control over which thread the Future runs on, Futures can be cancelled, and debugging information is available.</div>
<div dir="auto"><br></div>
<div dir="auto">You could imagine `async` as a syntax sugar for Future, e.g. the above Future example could be:</div>
<div dir="auto"><br></div>
<div dir="auto">
<div dir="auto"><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">func processImageData1() async -&gt; Image {</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px">
<span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">&nbsp; &nbsp; let dataResource &nbsp;= loadWebResource("dataprofile.</span><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">t<wbr>xt") // dataResource and imageResource run in parallel.</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px">
<span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">&nbsp; &nbsp; let imageResource = loadWebResource("imagedata.</span><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">dat<wbr>")</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px">
<span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">&nbsp; &nbsp; let imageTmp &nbsp; &nbsp; &nbsp;= decodeImage(dataResource.get ?? Resource(path: "Default data resource or prompt user"), imageResource.get ?? Resource(path: "Default image resource or prompt user"))</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px">
<span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">&nbsp; &nbsp; let imageResult &nbsp; = &nbsp;dewarpAndCleanupImage(</span><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">imageTm<wbr>p.get ?? Image(dataPath: "Default image or prompt user", imagePath: "Default image or prompt user"))</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px">
<span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">&nbsp; &nbsp; return imageResult.get ?? Image(dataPath: "Default image or prompt user", imagePath: "Default image or prompt user")</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px">
<span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">}</span><br></div>
<div dir="auto"><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)"><br></span></div>
<div dir="auto">Since an async is sugar for Future the async runs as soon as it is created (as soon as the underlying Future is created) and get returns an optional (also cancel and status would be still be present). Then if you want control over threads and timeout they could be arguments to async:</div>
<div dir="auto"><br></div>
<div dir="auto"><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)">func processImageData1() async(queue: DispatchQueue.main, timeout: .seconds(5)) -&gt; Image { ... }</span><br></div>
</div>
<br>
<div class="gmail_quote">
<div>On Sat, 26 Aug 2017 at 11:00 pm, Florent Vilmart &lt;<a href="mailto:florent@flovilmart.com" target="_blank">florent@flovilmart.com</a>&gt; wrote:<br></div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div>
<div name="messageBodySection">Howard, with async / await, the code is flat and you don’t have to unowned/weak self to prevent hideous cycles in the callbacks.<br>
Futures can’t do that</div>
</div>
<div>
<div name="messageReplySection"><br>
On Aug 26, 2017, 04:37 -0400, Goffredo Marocchi via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;, wrote:<br>
<blockquote type="cite">With both he now built in promises in Node8 as well as libraries like Bluebird there was ample time to evaluate them and convert/auto convert at times libraries that loved callback pyramids of doom when the flow grows complex into promise based chains. Converting to Promises seems magical for the simple case, but can quickly descend in hard to follow flows and hard to debug errors when you move to non trivial multi path scenarios. JS is now solving it with their implementation of async/await, but the point is that without the full picture any single solution would break horribly in real life scenarios.<br>
<br>
<div id="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259m_-2707032511043914185m_-3623957891747021796AppleMailSignature">Sent from my iPhone</div>
<div><br>
On 26 Aug 2017, at 06:27, Howard Lovatt 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>
<div>My argument goes like this:
<div><br>
<div>&nbsp; 1. You don't need async/await to write a powerful future type; you can use the underlying threads just as well, i.e. future with async/await is no better than future without.&nbsp;</div>
<div><br></div>
<div>&nbsp; 2. Since future is more powerful, thread control, cancel, and timeout, people should be encouraged to use this; instead because async/await are language features they will be presumed, incorrectly, to be the best way, consequently people will get into trouble with deadlocks because they don't have control.</div>
</div>
<div><br></div>
<div>&nbsp; 3. async/await will require some engineering work and will at best make a mild syntax improvement and at worst lead to deadlocks, therefore they just don't carry their weight in terms of useful additions to Swift.</div>
<div><br></div>
<div>Therefore, save some engineering effort and just provide a future library.</div>
<div><br></div>
<div>To turn the question round another way, in two forms:</div>
<div><br></div>
<div>&nbsp; 1. What can async/wait do that a future can't?</div>
<div><br></div>
<div>&nbsp; 2. How will future be improved if async/await is added?</div>
<div><br></div>
</div>
<div class="gmail_extra"><br clear="all">
<div>
<div class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259m_-2707032511043914185m_-3623957891747021796gmail_signature" data-smartmail="gmail_signature">&nbsp; -- Howard.<br></div>
</div>
<br>
<div class="gmail_quote">On 26 August 2017 at 02:23, Joe Groff <span>&lt;<a href="mailto:jgroff@apple.com" target="_blank">jgroff@apple.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word">
<div><br>
<div>
<blockquote type="cite">
<div>On Aug 25, 2017, at 12:34 AM, Howard Lovatt &lt;<a href="mailto:howard.lovatt@gmail.com" target="_blank">howard.lovatt@gmail.com</a>&gt; wrote:</div>
<br class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259m_-2707032511043914185m_-3623957891747021796m_1547456930512826529Apple-interchange-newline">
<div><span 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;float:none;display:inline!important"><span class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259m_-2707032511043914185m_-3623957891747021796m_1547456930512826529Apple-converted-space">&nbsp;</span>In particular a future that is cancellable is more powerful that the proposed async/await.</span></div>
</blockquote>
</div>
<br></div>
<div>It's not more powerful; the features are to some degree disjoint. You can build a Future abstraction and then use async/await to sugar code that threads computation through futures. Getting back to Jakob's example, someone (maybe the Clang importer, maybe Apple's framework developers in an overlay) will still need to build infrastructure on top of IBActions and other currently ad-hoc signalling mechanisms to integrate them into a more expressive coordination framework.</div>
<div class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259m_-2707032511043914185m_-3623957891747021796HOEnZb"><font color="#888888"></font>
<div><font color="#888888"><br></font></div>
<div><font color="#888888">-Joe</font></div>
</div>
</div>
</blockquote>
</div>
<br></div>
</div>
</blockquote>
<blockquote type="cite">
<div><span>______________________________<wbr>_________________</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/mailma<wbr>n/listinfo/swift-evolution</a></span><br></div>
</blockquote>
</blockquote>
</div>
</div>
</blockquote>
</div>
</div>
<div>--<br></div>
<div class="m_1881708220171369895m_7892036109698415928m_-5529795080384604611m_-5513424802125435497m_3268121293463145259m_-2707032511043914185gmail_signature" data-smartmail="gmail_signature">-- Howard.</div>
</div>
</blockquote>
<blockquote type="cite">
<div><span>______________________________<wbr>_________________</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/mailma<wbr>n/listinfo/swift-evolution</a></span><br></div>
</blockquote>
</div>
</div>
</div>
</div>
</blockquote>
</div>
<br></div>
</div>
</blockquote>
</blockquote>
</div>
</div>

</div></blockquote></div><br></div></div></div></div></div></div>______________________________<wbr>_________________<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/mailma<wbr>n/listinfo/swift-evolution</a><br>
</blockquote></div></div></div>
</div></blockquote></div><br></div></div></blockquote></div>
</div></blockquote></div><br></div></div></div>______________________________<wbr>_________________<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/mailma<wbr>n/listinfo/swift-evolution</a><br>
</blockquote></div></div>
______________________________<wbr>_________________<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" target="_blank">https://lists.swift.org/mailma<wbr>n/listinfo/swift-evolution</a><br></div></blockquote></div></div></div><br></div><br>______________________________<wbr>_________________<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/mailma<wbr>n/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div>
</div></blockquote></div><br></div></div></div></blockquote></div><br></div>
</div></blockquote></body></html>