On Apr 25, 2014, at 9:10 AM, Allen Wirfs-Brock <[email protected]> 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
[email protected]
https://mail.mozilla.org/listinfo/es-discuss