Block lambda is cool, its syntax isn't

Brendan Eich brendan at mozilla.com
Wed Jan 18 23:27:22 PST 2012


> François REMY <mailto:fremycompany_pub at yahoo.fr>
> January 18, 2012 12:54 PM
> To be fair, after a long reflection, I have been concluding that no 
> other proposal beat {|| ...} for block lambda at this time. Also, I’ve 
> found some use cases where block-lambda are actually useful (something 
> I was really curious about before thinking about it). In the future, 
> they may even be used a lot by transpilers to emulate new language 
> constructs in a ES-friendly way.

Indeed -- and it's good to read this paragraph.
> The main point I dislike with the current proposal is that it makes 
> block-lambda used at places where I think they should not. It’s not 
> because they are useful to solve some problems they are useful to fix 
> all. Most of the time, when we want a lambda, we don’t want TCP. We 
> want a new function.

I'm not sure about "most", but you are right that we don't want one 
hammer for all nails. We have function already. It wants shorter syntax 
(some say). Providing block-lambdas does not help there, and may tempt 
misuse of block-lambda where function is better, just because of 
block-lambda's conciseness.

> Just and only that. Since we want a new function, we are requesting 
> function-like semantics. It’s logical.
> An exemple:
>     function A() {
>      let ret = {|x| return x; };
>      let inc = {|x| x+1 };
>      let j = 0;
> while (true) {
> if (j > 3) ret(j);
>       j = inc(j);
>      }
>     }
> I don’t think “inc” should be a block-lambda. It can be, if someone do 
> that, I would not bother modifying the code. But it’s not the natural 
> way to think.

The TCP does help here, IMHO -- no 'return'.

> What we need here is not an “extension” of the current function (which 
> is a block lambda is), we need a new function.

Yet 
http://wiki.ecmascript.org/doku.php?id=strawman:arrow_function_syntax is 
in decline. But more below on that.
> The problem is that the current syntax is too long :
>     let inc = function(x) { return x+1; }

It's not just the length -- the 'return' and arguably even the braces 
are too much for an expression-bodied function.
> I think (/but I don’t say it’s what should be done, it’s up to 
> debate/) that alongside block-lambda, we should introduce a 
> ‘canonical’ lambda proposal, that would just be syntaxic sugar for 
> plain old functions.

Let's try not to use "lambda" two different ways, one of them not TCP. 
Lambda calculus and LISP fans want TCP.
> The syntax I propose would be:
>     ‘@(‘ + <argument-list> + ‘)’ + <statement>;

Two problems:

1. The semicolon can't be required, and if it isn't, then an Expression 
or AssignmentExpression statement as body inverts precedence fatally, 
because a function expression is a PrimaryExpression (ES6 fix, ES1-5 had 
it as MemberExpression, unobservably different and still high 
precedence). See

https://mail.mozilla.org/pipermail/es-discuss/2008-October/007883.html

Adapting to your proposal:

function f() {return "f"}
var x = 3;
g = ->  (a) a ? f : x++(1);


To fix (1), we want not simply a shorthand for high-precedence 
FunctionExpression, rather a new low-precedence production, as in 
arrow_function_syntax:

AssignmentExpression :
     ArrowFunctionExpression
     ...

Parenthesization will be required to use this kind of expression with 
higher precedence operators than , and = but those are rare operators 
with which to join any kind of function expression to other operators, 
with the possible exception of ( Arguments ) to invoke immediately. 
Immediate invocation would require parenthesizing the callee.

2. @ is wanted for private names. The precedent in Ruby and CoffeeScript 
for instance variables is strong.
> // or if too complex
>     ‘@(‘ + <argument-list> + ‘)’ + ‘{‘ + <statement> + ‘}’;

Definitely no ; at end here -- but this one is ok because the braces 
avoid precedence inversion.

To fix (2), how about reviving arrows and avoiding the non-LR(1) parsing 
for grammar validation problem?

ArrowFunctionExpression :
     ->  ArrowFormalParameters_opt AssignmentExpression
     ->  ArrowFormalParameters_opt ArrowBodyBlock_opt

ArrowFormalParameters :
     ( FormalParameterList_opt )
     ( this Initialiser_opt )
     ( this Initialiser_opt , FormalParameterList )


Someone with nick satyr mentioned this to me on irc.mozilla.org #jslang 
just recently, referencing Ruby 1.9 and Perl6.

If this looks good I can edit 
http://wiki.ecmascript.org/doku.php?id=strawman:arrow_function_syntax 
and remove the words in it that set it up as a mutually exclusive 
alternative to 
http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival.

> Please note that the last one seems very complex to write using a 
> block-lambda :
>     array.map({|x|let returnValue;
>         while(x.parentNode) {
>             x=x.parentNode;
>             if(x.tagName==’DIV’) { returnValue=x; break; }
>         }
>         if(returnValue) {
>             returnValue;
>         } else {
>             console.log(‘An element that has no parent DIV has been 
> found.’);
>             undefined;
>         }
>     });

Good point. Function wins due to early return, we've talked about 
extensions to block-lambdas to help but they still lose IMHO.
> That proposal does offer some middle ground between
> - ‘functions’ (classical functions)
> - ‘lambdas’ which are local functions that are not meant to go outside 
> the scope of an action

Again, 'lambda' is a misnomer, both for losing TCP and because you are 
simply providing shorter syntax (a function-rose by any other name would 
smell as sweet).

What's more, you are distinguishing syntax not semantics: the two 
bullets above are semantically equivalent. One from syntax in the 
language today, the second induced by shorter syntax (I propose revived 
arrow-in-front function syntax).

> - ‘block-lambdas’ which are internal functions that are not meant to 
> go outside the scope of a function scope.

Generally downward funarg only, yes. Still as you say some uses such as 
'inc' might get away with escaping and be called later, without error.

> Anyone can use what’s the most convenient for him, I think there’s 
> room for all those things.

I agree, since the shorter function syntax is "just syntax".

What do you think of prefixing -> to revive arrow function syntax?

/be



More information about the es-discuss mailing list