A syntax alternative for generators (was: Generator issue: exceptions while initializing arguments)
Allen Wirfs-Brock
allen at wirfs-brock.com
Tue Sep 11 09:40:43 PDT 2012
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:
On Sep 9, 2012, at 11:32 PM, Brendan Eich wrote:
>
> function dataSnapshot(aCollection) {
> let snapshot = aCollection.clone();
> return function*() {
> for (let i = 0; i < snapshot.length; i++){
> yield snapshot[i];
> }
> }();
> }
>
Issues:
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.
If the factory is a method the wrapping creates confusion about this/super binding. For example:
class MyClass {
dataSnapshot(aCollection) {
let snapshot = aCollection.clone();
return function*() {
for (let i = 0; i < snapshot.length; i++){
yield thls.doSomething(snapshot[i]); //this is not what was probably expected, super would be illegal
}
}();
}
}
Generator function definitions need to be called to create an actual iterator object (a generator instance)
It is likely that a common error will be forgetting the invocation of the generator in return statements such as the above.
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:
function IteratorCol(col = CollectionManager.default()) {
return function*() {for (let i = 0; i < col.length; i++) yield col[i]}();
}
is argubaly clearer and more likely to be correct than
function *IteratorCol(col = CollectionManager.default()) {
for (let i = 0; i < col.length; i++) yield col[i];
}
But the wrapper form is less concise than the unwrappered form.
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.
A different approach:
eliminate formal parameters from generator definitions -- if arguments are needed use a wrapper function/method
eliminate the need to call a generator before before using it as an iterator. Generator definitions create generator instances rather than generator constructor functions.
use lexical this/super binding within generator definitions
base generator definition syntax off of arrow function syntax rather than function definition syntax
eliminate concise generator methods
Examples:
function dataSnapshot(aCollection) {
let snapshot = aCollection.clone();
return *=>{
for (let i = 0; i < snapshot.length; i++){
yield snapshot[i];
}
};
}
or more concisely:
function dataSnapshot(aCollection) {
let snapshot = aCollection.clone();
return *=>for (let i = 0; i < snapshot.length; i++) yield snapshot[i];
}
as a method:
class MyClass {
dataSnapshot(aCollection = CollectionManager.default()) {
let snapshot = aCollection.clone();
return *=>for (let i = 0; i < this.length; i++) yield this[i];
}
}
Proposal summary:
Generator literals -- Base generators syntax on arrow functions rather than function declarations/expressions
lexical this/super
expression or curly body
Generator literals don't have formal parameters
Generators aren't called -- generator literals create generator instances (a kind of iterator) when evaluated
No concise generator methods -- use a concise method returning a generator literal
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20120911/99229971/attachment.html>
More information about the es-discuss
mailing list