April 10 2014 Meeting Notes

David Herman dherman at mozilla.com
Tue Apr 29 16:47:55 PDT 2014

On Apr 25, 2014, at 9:10 AM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:

> People will write code like this if we allow it.  But we don't have to allow.  We can preserve the semantics of try-finally by simply making the occurrence of the 'yield' operator syntactically illegal within the try block of a try-finally. 
> We could do this.  The parameterized grammar notation we now use in the ES6 spec. makes it fairly easy to specify that you can't write code like the above.  
> Should we do it?  I'm not sure.  I still think that @@return is a reasonable but imperfect alternative that allows generator authors to continue to use what many think is a useful feature.  Outlawing 'yield' in a try-finally is a almost perfect solution to the semantic impedance mismatch between try-finally and generators. But we also loose some expressiveness.

Promised you a reply to this one, sorry -- I'm not comfortable with this restriction. It violates my Schemer's intuition [1]. In particular it creates a number of refactoring hazards: (1) add some try/finally code around code to deal with something other than the yield it contains; (2) refactor some try/finally code outside of a generator into a generator.

Here's my perspective:

- Iterators should generally be short-lived.
- We should optimize the language design around ensuring that they will generally be exhausted.
- In most use cases users won't even touch an iterator directly; it'll just be created and passed directly into the for-of loop (or a combinator, which itself will often be implemented with a generator function that consumes the wrapped iterator in a for-of loop).
- The fact that iterators are first-class objects means it's *possible* to prevent an iterator from being terminated, but termination is never an absolute guarantee in Turing-complete languages to begin with.

So the design I favor is:

- Generators always have a .return() method.
- All three of .next, .throw, and .return should take an optional argument.
- All three of .next, .throw, and .return should return an iteration record ({ value: any, done: boolean }).
- The semantics of for-of (as well as any combinators we specify post-ES6) should call .return() on the underlying iterator iff there's an abrupt completion. If the iterator terminates itself the loop should not force a .return() -- this isn't just a performance compromise, it avoids calling .return() on a closed generator.
- If the implicit .return() of a for-of loop produces done: false, that indicates the iterator refused to be terminated, and the for-of loop should throw an exception. (This exception should throw from outside the loop, so no catch blocks inside the loop should catch it.)


[1] "Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary."

More information about the es-discuss mailing list