<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>The initializing generator arguments thread and related discussions has got me questioning our use of function declaration/expression syntax as our basis for defining generators.  Changing this would be a departure from what Firefox has supported in recent years, but in ES6 we have more constructs to build upon than FF did in 2006. The conclusion I reach is that it might be better to build generator definition upon a foundation of arrow functions rather than classic JS function definitions.  What follow is an attempt to sketch the thought process that lead to that conclusion:</div><div><br></div><br><div><div>On Sep 9, 2012, at 11:32 PM, Brendan Eich wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div><br>function dataSnapshot(aCollection) {<br>  let snapshot = aCollection.clone();<br>  return function*() {<br>    for (let i = 0; i < snapshot.length; i++){<br>      yield snapshot[i];<br>    }<br>  }();<br>}<br><br></div></blockquote></div><div><br></div><div>Issues:</div><div><ul class="MailOutline"><li>If a generator needs to capture creation time state  it needs to be wrapped in a factory function/method, similar to Brendan's example above.</li><li>If the factory is a method the wrapping creates confusion about this/super binding.  For example:</li></ul></div><div>class MyClass {</div><div>   dataSnapshot(aCollection) {<br>        let snapshot = aCollection.clone();<br>        return function*() {<br>               for (let i = 0; i < snapshot.length; i++){<br>                    yield <font class="Apple-style-span" color="#ff201a">thls</font>.doSomething(snapshot[i]);   <font class="Apple-style-span" color="#ff201a">//this is not what was probably expected, super would be illegal</font><br>               }<br>         }();<br><div>    }<br></div></div><div>}</div><div><br></div><div><ul class="MailOutline"><li>Generator function definitions need to be called to create an actual iterator object (a generator instance)</li><li>It is likely that a common error will be forgetting the invocation of the generator in return statements such as the above.</li><li>There is a potential for confusion about the evaluation time of generator parameter default value expression. If a parameterized generator needs default value initialization it is probably  better practice to accomplish that via a wrapper factory: </li></ul></div><div>function IteratorCol(col =  CollectionManager.default()) {</div>   return function*() {for (let i = 0; i < col.length; i++) yield col[i]}();<div>}</div><div><br></div><div>is argubaly clearer and more likely to be correct than</div><div><br></div><div><div>function *IteratorCol(col =  CollectionManager.default()) {</div>   for (let i = 0; i < col.length; i++) yield col[i];<div>}</div></div><div><ul class="MailOutline"><li>But the wrapper form is less concise  than the unwrappered form. </li><li>Concise method declarations for generators are misleading about the interface of the containing class/object because they place emphasis on an implementation detail (use of a generator to provide an Iterator implementation) rather than the more important fact that the method returns a object that can be used as an iterator.</li></ul></div><div><br></div><div>A different approach:</div><div><ul class="MailOutline"><li>eliminate formal parameters from generator definitions -- if arguments are needed use a wrapper function/method</li><li>eliminate the need to call a generator before before using it as an iterator.  Generator definitions create generator instances rather than generator constructor functions.</li><li>use lexical this/super binding within generator definitions</li><li>base generator definition syntax off of arrow function syntax rather than function definition syntax</li><li>eliminate concise generator methods</li></ul><div><br></div></div><div>Examples:</div><div><br></div><div>function dataSnapshot(aCollection) {<br> let snapshot = aCollection.clone();<br> return *=>{<br>   for (let i = 0; i < snapshot.length; i++){<br>     yield snapshot[i];<br>   }<br> };<br><div>}</div></div><div><br></div><div>or more concisely:</div><div><br></div><div><div>function dataSnapshot(aCollection) {<br> let snapshot = aCollection.clone();<br> return *=>for (let i = 0; i < snapshot.length; i++) yield snapshot[i];<br><div>}</div></div></div><div><br></div><div>as a method:</div><div><div><br></div></div><div><div>class MyClass {</div><div>   dataSnapshot(aCollection = CollectionManager.default()) {</div><div>        let snapshot = aCollection.clone();<br>        return *=>for (let i = 0; i < this.length; i++) yield this[i];<br><div>    }<br></div></div><div>}</div></div><div><br></div><div><br></div><div><br></div><div>Proposal summary:</div><div><ul class="MailOutline"><li>Generator literals -- Base generators syntax on arrow functions rather than function declarations/expressions</li><ul><li>lexical this/super</li><li>expression or curly body</li></ul><li>Generator literals don't have formal parameters </li><li>Generators aren't called -- generator literals create generator instances (a kind of iterator) when evaluated</li><li>No concise generator methods -- use a concise method returning a generator literal </li></ul></div><div><br></div></body></html>