yield* desugaring

Brendan Eich brendan at mozilla.com
Tue Apr 30 00:47:36 PDT 2013


Andy Wingo wrote:
> Hi Brendan,
>
> On Mon 29 Apr 2013 21:33, Brendan Eich<brendan at mozilla.com>  writes:
>
>> Andy Wingo wrote:
>>> close() does not seem to have much value given that it isn't part of the
>>> iterators specification, and one can do any needed action by doing a
>>> throw() on the iterator and relying on the generator to have a finally
>>> block if needed.
>> But throwing has other unwanted effects, in general. First, you need to
>> define a generator and give it a name. Then, close callers need to throw
>> that exception. For this reason, Python defined a built-in exception,
>> GeneratorExit.
>
> In Python, the close() method has some interesting interactions with
> finally:
>
>      >>>  def foo():
>      ...   try:
>      ...     yield 1
>      ...   finally:
>      ...     yield 2
>      ...
>      >>>  o = foo()
>      >>>  o
>      <generator object foo at 0x7feb31184f00>
>      >>>  o.__next__()
>      1
>      >>>  o.close()
>      Traceback (most recent call last):
>        File "<stdin>", line 1, in<module>
>      RuntimeError: generator ignored GeneratorExit

JS1.7 and up in SpiderMonkey (and I expect Rhino; this was all from ES4):

./Darwin_DBG.OBJ/js
js> function foo() {
   try {
     yield 1;
   } finally {
     yield 2;
   }
}
js> o = foo()
({})
js> o.next()
1
js> o.close()
typein:5:0 TypeError: yield from closing generator function foo() {
typein:5:0   try {
typein:5:0     yield 1;
typein:5:0   } finally {
typein:5:0     yield 2;
typein:5:0   }
typein:5:0 }


> Incidentally, close() is not the same as forcing a return:
>
>      >>>  def bar():
>      ...   try:
>      ...     return 1
>      ...   finally:
>      ...     yield 2
>      ...
>      >>>  bar().__next__()
>      2

That does not show close in action, though. The generator-iterator runs 
once there, yielding 2.

Yes, return in try runs finally, but that's independent of close and 
indeed of generators.

> Python's use case is also different because it specifies that when the
> generator object is finalized, the close() method gets called --
> certainly something we don't want to do for ES6.

Quite. Long-ago es4-discuss threads covered all of this.

https://mail.mozilla.org/pipermail/es-discuss/2006-December/
https://mail.mozilla.org/pipermail/es-discuss/2007-January/

Look for "Immediate closing of iterators".

> ES6 certainly won't provide a guarantee that finally blocks will run, so
> it seems to me that the main reason for close() is gone.

The JS1.7 prototype for ES4 ran close automatically only from for-in 
(which evolved into ES6's for-of). That's still on the table.

> I think we should leave the close() method out of the spec.

See above. Automating generator close from for-of is straightforward:

js> function foo() {
   try {
     yield 1;
   } finally {
     print("glorp");
   }
}
js> for (let x of foo()) print(x)
1
glorp

It's useful too, with no obvious alternative when you need it.

/be


More information about the es-discuss mailing list