How would shallow generators compose with lambda?

Brendan Eich brendan at
Thu May 14 13:22:57 PDT 2009

On May 14, 2009, at 12:24 PM, Jason Orendorff wrote:

> 1. A lambda can escape and be called from other code.  So both
> implementation approaches must be modified:
> * The CPS transformation would have to be applied to almost all
> functions, even functions not lexically inside the generator-function.
> This is a major change.
> * The stack-snapshot approach would have to store (a reference to) a
> range of stack frames, which may include frames for functions not
> lexically inside the generator-function. This might be a minor change.
> So much for duality. :-|

It's overrated :-P.

But this may be a problem with lambdas as proposed, not generators per  

> 3. When a lambda yields, the lines of code corresponding to the
> topmost captured frame (or, the beginning of the delimited
> continuation) and the bottommost (the tail end of the delimited
> continuation) are both lexically inside the generator-function. But
> there may be other functions on the stack, in between. You can't
> always statically tell which ones.  This means that generator
> semantics affect the integrity of code that isn't in a generator.

Right. We crossed the finally-may-not-run Rubicon along with Python  
(with a minor improvement, avoiding GeneratorExit), already, for  
finally clauses in the generator function itself. But this extends the  
finally integrity degradation outside of the lexical scope of the  
generator function. Good point.

> In ES5, when you call a function, you can expect it to return or throw
> eventually.  (Unless you run out of memory, or time, and the whole
> script gets terminated.)  With shallow generators, this is still true.
> A 'yield' might never return control, but function calls are ok.  But
> with generators+lambdas, almost any function call *anywhere* in the
> program might never return or throw.  This weakens 'finally', at
> least.

To make this clear with an example (thanks to Jason for some IRC  

function gen(arg) {
     foo((lambda (x) yield x), arg);
function foo(callback, arg) {
     try {
     } finally {
         alert("I'm ok!");
g = gen(42);
print(; // tell the user the meaning of life, etc.
g = null;

I think finally is the only issue, since how else can you tell that  
foo didn't see a return or exception from the callback?

It's true that this finally-may-not-run wrinkle is confined to  
generator functions in JS1.7, i.e., without lambda.

But I think any function that invokes an arbitrary other function in a  
try has to fear that its finally might not run. There could be a hard  
stop due to iloop prevention, or an uncatchable security fail-stop  

FWIW I'm cool on lambda and return to label atm.


More information about the es-discuss mailing list