Generator issue: exceptions while initializing arguments

Brendan Eich brendan at mozilla.org
Sat Sep 8 13:37:46 PDT 2012


Allen Wirfs-Brock wrote:
> This is the first of probably several semantic issues WRT generator 
> that will need to be resolved in the spec.
>
> Here is the user level issue:
>
> let thrower = {throw () {throw "exception"}};
> function * G(arg = thrower.throw()) {
>    //possibly other explicit initialization code which could also throw
>    yield arg;
> }
> let g = G();   //do we see "exception" here?  (loc 1)
> ... //possibly many lines of code
> g.next();       //or do we see it here (loc 2)

Python is no help since its parameter default values are evaluated when 
the definition is evaluated, not on each call:

Python 3.2 (r32:88452, Feb 20 2011, 11:12:31)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
 >>> def thrower():
...   raise BaseException('exception')
...
 >>> def G(arg = thrower()):
...   yield arg
...
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "<stdin>", line 2, in thrower
BaseException: exception

> The generator proposal [1] doesn't really address this issue.  It 
> assumes [2] that an environment record with the parameter bindings can 
> be created and captured at loc 1 without triggering any exceptions and 
> it defers instantiation and execution of all of the generator's code 
> body until the first "next" call.

Sure, the proposal predates parameter default values and has not been 
updated to take them into account. Thanks for raising this issue.

>  However, the semantics of parameter default value initialization can 
> result in exceptions and more closely links argument instantiations 
> with the actual activation of the generator function. You can't really 
> build the parameter bindings without performing declaration 
> instantiation for the function.

Agreed, that's absolutely true (no "really" about it -- or rather, "for 
real" ;-).

> Arguably, exceptions involving initialization of the the parameter 
> would be more meaningful at loc 1  (loc 2 could be very remote and in 
> somebody else's code). However, the body of the generator may contain 
> other explicit initialization code and there really is no way to 
> identify and move evaluation of that code (and its possible 
> exceptions) to loc 1. So, even if parameter initialization exceptions 
> are made observable at loc 1 there may still be other logical 
> initialization-related exceptions that will onlybe  observable at loc 2.

That's fine because those loc2 exceptions originate from code explicitly 
in the generator function's body -- after the opening brace.

> Which semantics do we want?  Deferring parameter initialization to loc 
> 2 may be somewhat simpler from a specification perspective.  It's hard 
> to say which would have bigger implementation impact.

The implementation is not hard in any event, as it involves an implicit 
(yield); statement inserted before the first evaluation of anything 
explicitly in the body.

Possible side effects from "binding arguments to parameters" should be 
observed early, at loc 1, for the reason you give: late means something 
will be missed, or happen out of order. For me this is the clincher.

Cc'ing Jason for his thoughts.

/be

>
> Allen
>
> [1]: http://wiki.ecmascript.org/doku.php?id=harmony:generators
> [2]: http://wiki.ecmascript.org/doku.php?id=harmony:generators#calling
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss


More information about the es-discuss mailing list