Block Lambdas: break and continue

Allen Wirfs-Brock allen at wirfs-brock.com
Mon Jan 16 09:53:08 PST 2012


On Jan 15, 2012, at 11:16 PM, Brendan Eich wrote:

> 
> I think you are forgetting the for(;;) loop. Paren-ful for loop:

yup, I thought the "Paren-free" reference was regarding paren-free calls.   Paren-free in other context does indeed create ambiguities with my suggests. I had thought that paren-free outside of block-lambda calls was pretty much dead, but as you say it could be a future possibility so that needs to be factored into the discussion.


> ...
>> but I agree we could do block lambdas while deferring extended break/continue semantics .  But this does seem like a neat approach.
> 
> I'm not slamming the door, but I do not want to lumber block-lambdas with more complexity if the hard case is as rare as I contend. Anyway "neat" is not enough. We need an unambiguous prefix syntax.

I agree, this is exactly where I was until Grant's idea came along and seemed worth exploring.  But if we want to future proof for full paren-free then I think we should simply defer any consideration of block-lambda friendly break/continue

> 
> ...
>> Or consider in as a prefix operator:
>> 
>> in arr.forEach { |o|
>>      if (...) break;
>> }
> 
> Horribly ambiguous, ES3 and up do not forbid line terminator to left of 'in' operator.

yup, missed that one

>> 
>> or
>> 
>> here: in arr.forEach { |o|
>>      elsewhere: while (true) {
>>       if (...) break here; else break elsewhere;
>> }
> 
> The labels mean you don't need "in" at all:

Yes, I like that.

> 
> here: arr.forEach { |o|
>      elsewhere: while (true) {
>       if (...) break here; else break elsewhere;
> }
>   
> What was the "in" for again? No "continue" usage here, which is more awkwardly translated to a break from inner labeled block as Grant showed. But continue is an even rarer hard case.

I forget the "in" but  it is better without it.

I see the main value of |continue| in block lambdas simply as an early exist from the lambda Just like with |return| in a normal function, it is sometimes clearer to do an explicitly early exist then to arrange the control flow to fall through to the end.  Grant's pattern, used explicitly, actually seems like a good solution for cases where the block's continuation value is no needed:
    foo  {||
       exit: {
            ...
            if (...) break exit;
            ...
        }
   };

However, block lambdas are often evaluated for a value and none of the current continue/break based solutions include a way to provide an explicit continuation value.  Here is an idea for that:

    foo  {||
       exit: {
            ...
            if (...) break exit with "early";  //[no LineTerminator here] before "with"
            ...
        }
   };




> 
>>> We could contextually reserve loop. But statements are part of JS, and so I suspect people would want this to do what Doug Crockford has suggested it to: indefinitely iterate its body (here the arr.forEach call expression statement, which would have a semicolon inserted automatically after). This is a conflict, since forEach does its own looping.
>> 
>> I suspect that learning that loop does do what Doug suggested is less of a burden than leaning what {||...} means.
> 
> Did you mean "does not"?
yes
> ...
> I repeat if you are willing to use a label, you don't need a prefix keyword. See Grant's desugarings.

Yes, I like that except for the completion value issue

Allen


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20120116/c552be1b/attachment-0001.html>


More information about the es-discuss mailing list