On Apr 25, 2014, at 9:10 AM, Allen Wirfs-Brock <al...@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.)

Dave

[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."
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to