yield* desugaring

Andreas Rossberg rossberg at google.com
Tue Apr 30 05:19:03 PDT 2013


On 30 April 2013 13:30, Andy Wingo <wingo at igalia.com> wrote:
> Hi Kevin,
>
> On Tue 30 Apr 2013 11:05, Kevin Gadd <kevin.gadd at gmail.com> writes:
>
>> I would definitely expect a given finally block to run if i use for-of
>> or similar on the generator. This is the intent, I hope?
>
> Certainly they run in this situation:
>
>   function *g1() { try { yield 1; } finally { qux(); } }
>   for (x of g1())
>     print (x)
>
> Or in this one:
>
>   function *g2() { try { yield 1; return; } finally { qux(); } }
>   for (x of g2())
>     print (x)
>
> But the question is what happens here:
>
>   function *g3() { try { yield 1; } finally { qux(); } }
>   for (x of g3())
>     break;
>
> Or here:
>
>   function *g4() { try { yield 1; } finally { qux(); } }
>   for (x of g4())
>     throw "foo";
>
> Or here:
>
>   function *g5() { try { yield 1; } finally { qux(); } }
>   for (x of g5())
>     call_function_that_throws_an_exception();
>
> For me, it is acceptable in the last three cases to never invoke those
> finally blocks.  Otherwise, for-of would need to be implicitly
> surrounded by a try/finally to manually "close" the generator.  It
> seems to me that it would have pretty negative perf implications; for
> example Crankshaft doesn't currently run on functions with try/finally.

A particular Crankshaft limitation may not be the most convincing
argument. :) But clearly, even without that, requiring an implicit
finally wrapper for every for-of loop could still be costly --
especially because the last case cannot easily be ruled out at compile
time.

I'd also argue that _not_ running the finally blocks of a generator in
cases where it is abandoned is consistent with coroutine semantics. In
those cases, the generator basically amounts to a coroutine that is
still active, but being starved because you never yield back to it
again.

Even if we did require a close with for-of loops, the problem would
still exist if a generator is run directly through its method
interface. There is no way the language can enforce a close in this
situation, short of finalization.

The moral is that one should simply avoid putting a yield inside a
try-finally. There is no guarantee that control ever returns.

/Andreas


More information about the es-discuss mailing list