<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Aug 23, 2017, at 12:06 AM, Martin Waitz &lt;<a href="mailto:tali@admingilde.org" class="">tali@admingilde.org</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="">Hello,<div class=""><br class=""></div><div class=""><div class=""><blockquote type="cite" class=""><div class="">Am 22.08.2017 um 18:32 schrieb Joe Groff via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt;:</div></blockquote><blockquote type="cite" class=""><div style="font-family: Helvetica; font-size: 13px; 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; -webkit-text-stroke-width: 0px;" class=""><div class="">The feature provides general delimited continuations. You could write an IteratorProtocol-conforming interface over a coroutine like this:</div><div class=""><br class=""></div></div><blockquote class="" style="font-family: Helvetica; font-size: 13px; 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; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><div class="">&nbsp;private func yield(_ value: T) async -&gt; Void {</div></div><div class=""><div class="">&nbsp; &nbsp;self.next = value</div></div><div class=""><div class="">&nbsp; &nbsp;await suspendAsync { cont in</div></div><div class=""><div class="">&nbsp; &nbsp; &nbsp;resume = cont</div></div><div class=""><div class="">&nbsp; &nbsp;}</div></div><div class=""><div class="">&nbsp;}</div></div><div class=""><div class=""><br class=""></div></div><div class=""><div class=""><br class=""></div></div></blockquote><div style="font-family: Helvetica; font-size: 13px; 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; -webkit-text-stroke-width: 0px;" class="">This isn't ideal in a number of ways (awkward, not particularly efficient, and has the gotcha that the generator's `body` could suspend itself with something other than the `yield` operation, doesn't integrate with ownership in the way John proposes in the ownership manifesto), so it may not be a good idea, of course.</div></blockquote><div class=""><br class=""></div><br class=""></div>I still have trouble understanding how exactly suspendAsync is going to work.<div class="">Is the body called right away or is it put into some dispatch queue on another thread?</div><div class="">Does the continuation function return immediately (besides queueing suspendAsync to also return)?</div></div></div></div></blockquote><div><br class=""></div><div>suspendAsync suspends the coroutine's context and passes it as a continuation into the body, which is executed immediately on the current thread.&nbsp;</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><div class="">How does this correlate with coroutines?</div><div class="">There is no extra stack for the coroutine (which runs the generator function), right?</div><div class="">In my mental model, the generator function is split into individual functions which are queued one after another, but reusing the same thread/stack, is this correct?</div></div></div></div></blockquote><div><br class=""></div><div>That's the way C# implements it, yeah, and it could be how we implement it as well. It would likely be the quickest way to get the feature up and running on existing platforms. I intentionally left the mechanism vague because there may be other implementation models we can explore within this model, such as running coroutines on their own lightweight growable stacks the way some other languages like Julia and recent versions of Go implement coroutines.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><div class="">How would a generator feature without the mentioned shortcomings look like?</div></div></div></div></blockquote><br class=""></div><div>The main thing missing from this model that generators need is a way to require a value to be yielded to the controlling context at each point the coroutine suspends itself. The proposal as written puts the responsibility for scheduling the continuation and passing data from async to sync into the caller of suspendAsync; this is good for async tasks since you don't generally want or need to expose dependencies on specific coordination mechanisms through an async task. One could complicate the model by making 'async' a typed effect, analogous to the frequently-requested "typed throws" feature, where the type of "async" is the type of value that is yielded back to the sync context at every suspension point.</div><div><br class=""></div><div>-Joe</div><br class=""></body></html>