Andreas Rossberg (2013-04-30T12:22:13.000Z)
On 30 April 2013 14:19, Andreas Rossberg <rossberg at google.com> wrote:
> 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.

And as Andy points out correctly, that raises the question whether
having 'close' makes much sense at all.

/Andreas
github at esdiscuss.org (2013-07-12T02:26:59.536Z)
On 30 April 2013 14:19, Andreas Rossberg <rossberg at google.com> wrote:
> On 30 April 2013 13:30, Andy Wingo <wingo at igalia.com> wrote:
>> 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.

And as Andy points out correctly, that raises the question whether
having 'close' makes much sense at all.