How would shallow generators compose with lambda?

Brendan Eich brendan at mozilla.com
Thu May 14 12:38:21 PDT 2009


We still have open controversy over lambdas, if I recall correctly.  
Separate thread, but I wanted to confirm that there is disagreement on  
completion value being the implicit return value, at least. Some  
strawman syntax for explicit result value was mooted.

I also seem to recall some folks (Waldemar in particular) thinking  
that lambdas are redundant, and also potentially confusing to average  
users precisely *because* of Tennant Correspondence being two-edged in  
languages that have statements as well as expressions. The question  
for naive readers is: "return" from what? The answer proposed is  
always from the nearest enclosing function (ignoring return to label),  
but some may stop at the nearest enclosing lambda, and resulting bugs  
might hide in plain sight.

On May 14, 2009, at 10:25 AM, Mark S. Miller wrote:

> A return in a lambda returns from the immediately containing function
> activation, so long as that function activation is still active. If
> the containing function has already returned, then a postponed attempt
> to return from it again will fail[1], presumably with a thrown error.
> This applies as well to break, continue, labeled break, labeled
> continue, and labeled return if we introduce such a thing. What
> happens to a postponed 'yield'?

Same thing: yield is very much like return, except that the activation  
is not deallocated because the generator-iterator g, created by  
calling a generator function f that contains yield expresssions, which  
was invoked via g.next(), g.send(v), or g.throw(e), holds a strong  
reference to that activation for generator function f.

So a lambda that tries to yield from a deactivated function that  
encloses it should fail with a big fat exception, same as for return.


> Also, does it make as much sense to
> introduce a labeled yield as it does to introduce a labeled return?

Return to label, aka "escape continuations", are motivated largely by  
the expression-oriented lambda proposal with its final expression  
evaluating to the return value, for working around the consequent lack  
of "early returns".

Note that return to label as proposed works in any labeled statement,  
and does not require a lambda to surround the return. It works via TC  
in lambdas just as return does. The motivation via lambda having  
implicit return of completion value is what connects the return to  
label and lambda proposals.

In this light, yield to label is plausible, although the "early/ 
exceptional return from lambda" motivation is missing in the sense  
that you can write yield expressions in larger expressions -- you  
can't use return in the middle of an expression. But yield to label  
could be just as useful as return to label.

The syntax works when the yield expression forms a complete expression  
statement:

     yield : expr;

but it requires parenthesization in the middle operand of the ?:  
ternary operator.

Indeed the low-precedence (same as assignment) nature of the yield  
unary caused JS1.7 to follow Python in requiring parentheses around  
yield expressions in lists: in comma expressions and actual parameter  
lists (although we diverged from Python by allowing an unparenthesized  
yield expression as the last actual argument in a call or new  
expression's parameter list -- Python requires foo((yield bar))  
instead of foo(yield bar)).

/be


More information about the es-discuss mailing list