Allen Wirfs-Brock (2013-05-12T19:29:26.000Z)
github at esdiscuss.org (2013-07-12T02:27:21.255Z)
I literally just finished making the changes to the ES6 specification draft to fully incorporate generator semantics. I'll will be making that draft available within the next day or two after worked down the bug backlog a bit. Because this thread started while I was in the middle of that work, I choose to ignore it until I had finished with it (with the exception, that I differed implementing `<generator>.close()` because I did notice that its utility was being questioned). I've now digested the thread and I want to provide some feedback on it that reflects my spec. work. First, as a general comment, I don't use direct desugaring within the spec. but instead use the spec. pseudo code formalisms. This gives me direct access to mechanisms such as internal Completion values and allows me to express behaviors that are difficult or impossible to express via desugarings. As now specified: 1. I specified `yield*` such that it will work with any iterator, not just generators. To me, this seems essential. Otherwise client code is sensitive to other peoples implementation decision (that are subject to change) regarding whether to use a generator or an object based iterator. This was easy to accomplish and only requires a one-time behavioral check to determine whether `next` or `send` should be used to retrieve values from the delegated iterator and an behavior guard on invoking `throw` on the delegated iterator. 2. `yield*` invokes the @@iterator method on its expression to obtain the iterator. This means you can say things like: ```js yield * [2,4,6,8,10]; //individually yield positive integers <= 10. ``` 3. `yield*` yields the `nextResult` object produced by the inner iterator. No unwrapping/rewrapping required. 4. I haven't (yet) provided a `close` method for generators. I still think we should. Unwinding via return is clearly the appropriate semantics for `close`. Contrary to some concerns expressed on this thread, I don't think there are any issues with distinguishing `close` triggered returns from actual user level concerns. Such returns (all returns) have to pass as Completion values through the outer body level of the generator and it is easy enough (at the spec level) for me to tag such returns (using a unique, unobservable internal return value) such that there is no confusion with an actual user level return. I think `close` is an useful and important operation for maintaining finally semantics in two use cases: 1.   ```js for (v of iterable) {...break;...} /* or return or throw or outer continue*/ ``` The `for`-`of` should should automatically invoke `close` if the loop is terminated before exhausting the iterator. The `close` needs to be guarded with a behavioral check just like I did for `yield*`. I think this is a common case and we really should be doing our best effort to maintain the reliability of `finally` blocks for this common case. 2. Any time user code is manually draining a known generator that it opened and decides that it is now done with the generator. They really should close it. Of course, they may not, but regardless they should be provided with a means to do so and it should be encouraged as a best practice. The second use case is perhaps a little iffy, but the first really seems fundamental to finally semantics and something that the language can automatically do. To me, it would seem a bit negligent to not handle that situation.