StopIteration, ForwardToTarget, ... & symbols

Allen Wirfs-Brock allen at
Tue Nov 27 17:02:55 PST 2012

On Nov 27, 2012, at 12:45 AM, Brendan Eich wrote:

> Allen Wirfs-Brock wrote:
>> There would be another way to accomplish supporting generator return values that doesn't require dynamically constructing new StopIteration instances and avoids all Realm issues:  Capture the return value in the generator instance when it enters the "closed" state and then throw the single immutable StopIteration object (could be a Symbol).  A client of the generator instance that catches StopIteration and expects a return value can directly query the generator instance (via a property access) to get that return value.  It accomplishes the same thing but doesn't require multiple StopIteration instances, an extract allocation on generator returns, a call to isStopIteration to test, etc.
> ...
> Not much of a change, but something crucial is lost. The try could possibly .send or .next another task's generator-iterator (task.thread), possibly under pump if it immediately dispatched (it doesn't, but suppose it did). You're programming by side effects here, requiring the catcher of e to know that task.thread.value is the mutable pigeon-hole to inspect.
> This smells pretty bad compared to the PEP-380 style alternative, which cleanly localizes the result to e.value.
It's always bothered me that there is do direct linkage between between a generator instance that might throw a StopIteration and the actual StopIteration value that is thrown.  In particular, if you catch StopIteration you don't know which generator instance may have thrown it.  I don't think this is an issue for for-of invoked generator instances but it might be an issue of mainly invoked generator instances such as those in a task scheduler.  There is nothing that prevents somebody invoking next an a generator/iterator without wrapping it with a try-catch.

So here is a new idea.  Why not throw the iterator/generator instance it self as the "stop iteration" exception instance.  For example:

function *myGenerator() {
    yield 1;
    return 2;

myGen = myGenerator();
try {
   while (true) doSomething(
}  catch (e)  {
   if (e===myGen()) doLast(myGen.returnValue);
   else throw e;

Someone calling a generator next method, by definition a a reference to the generator so has it available to look for as an exception object.


> /be

More information about the es-discuss mailing list