<!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 <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> </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> </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> </div>
<div>-Kevin</div>
<div> </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> </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> </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> </div>
<div>So for example:<br></div>
<div> </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?) -> String {<br></div>
<div> yield “Hello”<br></div>
<div> yield name ?? “World”<br></div>
<div>}<br></div>
</blockquote><div> </div>
<div>Would have the following expected usage:<br></div>
<div> </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> 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>// Hello<br></div>
<div>// 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> </div>
<div><div>And for those unfamiliar to these sorts of simple cases, would have equivalent behavior to the following code:<br></div>
<div> </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)"> 45> </span>func helloGenerator(name:String?) -> 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)"> 46. </span> return HelloGenerator(name) <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);"> 47. <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;color:rgb(169, 169, 169);"> 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)"> 49. </span>struct HelloGenerator : GeneratorType, SequenceType { <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)"> 50. </span> var position:Int = 0 <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)"> 51. </span> let name:String? <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);"> 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)"> 53. </span> private init(_ name:String?) { <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)"> 54. </span> self.name = name <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)"> 55. </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);"> 56. <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)"> 57. </span> func generator() -> 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)"> 58. </span> return self <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)"> 59. </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)"> 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)"> 61. </span> mutating func next() -> String? { <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)"> 62. </span> switch position { <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)"> 63. </span> case 0: <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)"> 64. </span> position = 1 <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)"> 65. </span> return "Hello" <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)"> 66. </span> case 1: <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)"> 67. </span> position = 2 <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)"> 68. </span> return name ?? "World" <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)"> 69. </span> default: <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)"> 70. </span> return nil <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)"> 71. </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)"> 72. </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);"> 73. <span class="colour" style="color:rgb(0, 0, 0)">} </span><br></div>
</div>
<div> </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> </div>
<div>The interaction with the error system might involve disallowing throws from generator functions, or having the Element type be a Result<T> rather than T, as the GeneratorType next() method is not declared as throwing.<br></div>
<div> </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> </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> </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> </div>
</body>
</html>