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