<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body><div>I'd love to have first-class support for generators like this, but it's a&nbsp;<i>lot</i> of work. It's a lot easier to do this sort of thing in a scripting language like Python than it is to do in a language like Swift, because it requires reifying the stack into a data structure that can be passed around. And I suspect there's a lot of non-trivial questions that have to get answered before you can even propose an implementation for this.<br></div>
<div>&nbsp;</div>
<div>For context, this sort of thing is something that people have been talking about doing in Rust for quite a while, and it keeps getting punted because of the amount of work and the unanswered questions about how it would actually be implemented.<br></div>
<div>&nbsp;</div>
<div>So I'll give this a general +1, but I think it should also be deferred until after Swift 3 at the earliest.<br></div>
<div>&nbsp;</div>
<div>-Kevin</div>
<div>&nbsp;</div>
<div>On Fri, Dec 11, 2015, at 04:21 PM, David Waite via swift-evolution wrote:<br></div>
<blockquote type="cite"><div>Looking for feedback on crafting a proposal adding generator functions to Swift. I understand this will likely be a very involved proposal at the language level, although I actually don’t know the complexity of the change within the Swift compiler itself.<br></div>
<div><div>&nbsp;</div>
<div><div>This would be a function which returns multiple values, which is converted by the compiler to a function returning a SequenceType<br></div>
<div>&nbsp;</div>
<div>A very basic syntax would be to add generator as a modifier to func, and likely involve a new keyword ‘yield’ to differentiate from the flow control behavior of ‘return’.<br></div>
<div>&nbsp;</div>
<div>So for example:<br></div>
<div>&nbsp;</div>
<blockquote style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:40px;border-top-style:none;border-right-style:none;border-bottom-style:none;border-left-style:none;border-top-width:initial;border-right-width:initial;border-bottom-width:initial;border-left-width:initial;border-top-color:initial;border-right-color:initial;border-bottom-color:initial;border-left-color:initial;border-image-source:initial;border-image-slice:initial;border-image-width:initial;border-image-outset:initial;border-image-repeat:initial;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;"><div>generator func helloGenerator(name:String?) -&gt; String {<br></div>
<div>&nbsp; &nbsp; yield “Hello”<br></div>
<div>&nbsp; &nbsp; yield name ?? “World”<br></div>
<div>}<br></div>
</blockquote><div>&nbsp;</div>
<div>Would have the following expected usage:<br></div>
<div>&nbsp;</div>
<blockquote style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:40px;border-top-style:none;border-right-style:none;border-bottom-style:none;border-left-style:none;border-top-width:initial;border-right-width:initial;border-bottom-width:initial;border-left-width:initial;border-top-color:initial;border-right-color:initial;border-bottom-color:initial;border-left-color:initial;border-image-source:initial;border-image-slice:initial;border-image-width:initial;border-image-outset:initial;border-image-repeat:initial;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;"><div>for str in helloGenerator(“David") {<br></div>
<div>&nbsp; &nbsp;print str<br></div>
<div>// prints:<br></div>
</blockquote><blockquote style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:40px;border-top-style:none;border-right-style:none;border-bottom-style:none;border-left-style:none;border-top-width:initial;border-right-width:initial;border-bottom-width:initial;border-left-width:initial;border-top-color:initial;border-right-color:initial;border-bottom-color:initial;border-left-color:initial;border-image-source:initial;border-image-slice:initial;border-image-width:initial;border-image-outset:initial;border-image-repeat:initial;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;"><div>// &nbsp; &nbsp;Hello<br></div>
<div>// &nbsp; &nbsp;David<br></div>
</blockquote><blockquote style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:40px;border-top-style:none;border-right-style:none;border-bottom-style:none;border-left-style:none;border-top-width:initial;border-right-width:initial;border-bottom-width:initial;border-left-width:initial;border-top-color:initial;border-right-color:initial;border-bottom-color:initial;border-left-color:initial;border-image-source:initial;border-image-slice:initial;border-image-width:initial;border-image-outset:initial;border-image-repeat:initial;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;"><div>}<br></div>
</blockquote><div>&nbsp;</div>
<div><div>And for those unfamiliar to these sorts of simple cases, would have equivalent behavior to the following code:<br></div>
<div>&nbsp;</div>
<blockquote style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:40px;border-top-style:none;border-right-style:none;border-bottom-style:none;border-left-style:none;border-top-width:initial;border-right-width:initial;border-bottom-width:initial;border-left-width:initial;border-top-color:initial;border-right-color:initial;border-bottom-color:initial;border-left-color:initial;border-image-source:initial;border-image-slice:initial;border-image-width:initial;border-image-outset:initial;border-image-repeat:initial;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;"><div><div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;45&gt; </span>func helloGenerator(name:String?) -&gt; HelloGenerator {&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;46. </span>&nbsp; return HelloGenerator(name)&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(169, 169, 169);">&nbsp;47. <span class="colour" style="color:rgb(0, 0, 0)">}&nbsp;</span><br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(169, 169, 169);">&nbsp;48. <span class="colour" style="color:rgb(0, 0, 0)"></span><br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;49. </span>struct HelloGenerator : GeneratorType, SequenceType {&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;50.&nbsp;</span> &nbsp; var position:Int = 0&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;51.&nbsp;</span> &nbsp; let name:String?&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(169, 169, 169);">&nbsp;52. <span class="colour" style="color:rgb(0, 0, 0)"></span><br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;53.&nbsp;</span> &nbsp; private init(_ name:String?) {&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;54. </span>&nbsp; &nbsp; &nbsp; self.name = name&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;55.&nbsp;</span> &nbsp; }&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(169, 169, 169);">&nbsp;56.&nbsp;<span class="colour" style="color:rgb(0, 0, 0)"></span><br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;57.&nbsp;</span> &nbsp; func generator() -&gt; HelloGenerator {<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;58.&nbsp;</span> &nbsp; &nbsp; &nbsp; return self&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;59.&nbsp;</span> &nbsp; }&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;60. </span><br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;61.&nbsp;</span> &nbsp; mutating func next() -&gt; String? {&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;62. </span>&nbsp; &nbsp; &nbsp; switch position {&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;63. </span>&nbsp; &nbsp; &nbsp; case 0:&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;64. </span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; position = 1&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;65. </span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return "Hello"&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;66. </span>&nbsp; &nbsp; &nbsp; case 1:&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;67. </span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; position = 2&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;68. </span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return name ?? "World"&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;69. </span>&nbsp; &nbsp; &nbsp; default:&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;70. </span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return nil&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;71. </span>&nbsp; &nbsp; &nbsp; }&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(169, 169, 169)">&nbsp;72.&nbsp;</span> &nbsp; }&nbsp;<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(169, 169, 169);">&nbsp;73. <span class="colour" style="color:rgb(0, 0, 0)">}&nbsp;</span><br></div>
</div>
<div>&nbsp;</div>
</blockquote><div>This syntax has at a bare minimum issues with generator closures and for a terse syntax for yielding over another sequence type within a generator function vs. using a loop. (possibly “yield in sequenceName”)<br></div>
</div>
<div>&nbsp;</div>
<div>The interaction with the error system might involve disallowing throws from generator functions, or having the Element type be a Result&lt;T&gt; rather than T, as the GeneratorType next() method is not declared as throwing.<br></div>
<div>&nbsp;</div>
<div><div>This could pair well to make for-in loops more comprehensive, especially if C-style for loops are eliminated.<br></div>
</div>
<div>&nbsp;</div>
<div>This would possibly be a first step toward a coroutine-based concurrency system, although I am not proposing that sort of usage or scope here. The goal would be to emit an object compatible with SequenceType<br></div>
</div>
<div>&nbsp;</div>
<div>-David Waite (DW)<br></div>
</div>
<div><img style="height:1px !important;width:1px !important;border-top-width:0px !important;border-right-width:0px !important;border-bottom-width:0px !important;border-left-width:0px !important;margin-top:0px !important;margin-bottom:0px !important;margin-right:0px !important;margin-left:0px !important;padding-top:0px !important;padding-bottom:0px !important;padding-right:0px !important;padding-left:0px !important;" border="0" height="1" width="1" alt="" src="https://www.fastmailusercontent.com/proxy/05c28cc715a04de9ed2dc8ec5fa467507674de467bfa927549974b548605edca/8647470737a3f2f25723030323431303e23647e23756e64676279646e2e65647f27766f2f60756e6f35707e6d3148765176786c673171614a7d2236454230345272776e4a57753c634b6850594740383f4f68595a7245367567453b403054327b4542683976525079765d683560557b44463e674a42416142447748516878695279615f63793f6a774a5469783d4834463754497c6f6a5635437a634539594e46576c695458385169666936497f493847714d223242517e686a734d22324240563d22324d2236493834534c61517c6e63493a4f464d22324a51395e447533754577534841363357654034496265454d2236444163553779387753536d2232474a674860507367354a73434f697562673759576d23344d23344/open"><br></div>
<div><u>_______________________________________________</u><br></div>
<div>swift-evolution mailing list<br></div>
<div><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br></div>
<div><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div>
</blockquote><div>&nbsp;</div>
</body>
</html>