On Apr 25, 2014, at 4:53 AM, Kevin Smith wrote:
> It seems to me that generators are not the best mechanism to express resource
> management ("abstract over expensive resources") because the programmer of
> the generator can never guarantee that the consumer will exhaust it. If we
> want direct language support for resource management, then a proposal should
> be crafted to add that as a distinct feature.
>
We routinely make use case based argument to justify new features. But once we
have a feature, we can't expect it to be used only for the original use cases
that motivated its inclusion. In integrating a feature we need to look at a
feature's actual semantics and how those semantics interact with the semantic
of existing and proposed features. At that point, we shouldn't be thinking
about whether a particular use case is "good" or "bad" . It is only the
semantic interactions that we should consider.
In this case we have try-finally statements as an existing feature. The
semantics of this feature is a bounded execution scope with a cleanup action on
completion. This feature is widely used and has always been internally
consistent and reliable, expect for catastrophic external failure or
intervention (ie, externally imposed process termination, power failure, etc).
People use it for all sorts of things, including bounded resource management.
We then added a new feature, generators, which in some cases changes the
semantics of try-catch. No longer is the execution of the try block bounded in
a manner that guarantees that the finally block will execute after completion
of the try block. That seems like a significant semantic change to try-finally
and a usage hazard that we should be concerned about.
Support for @@return and its use by for-of would help to restore the
try-finally invariants for what is likely to be the most commonly seen semantic
feature composition (I'm not taking about use cases here) of for-of,
generators, and try-finally. That's an imperfect solution because when for-of
isn't used it places a burden on the JS programmer to do manual work to ensure
the try-finally invariant of a (possibly) generator invocation. However, it
seems like a significant improvement over the currently spec. behavior which
just flat-out breaks a generator's try-finally invariant for any abrupt
termination of a for-of loop.
The @@return solution still seems like a good compromise design. However,
there is another way to attack this problem.
The fundamental problem is that any generator that looks anything like this:
function *f() {
try {yield} finally {postcondition()}
}
has an unreliable try-finally block. Whatever the programmer things is going
to happen, may not actually happen. The problem is the yield (a new feature
that is corrupting the legacy semantics of try-finally).
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.
Allen
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss