Block lambda is cool, its syntax isn't

Brendan Eich brendan at mozilla.com
Fri Jan 20 17:08:28 PST 2012


Rust is a static language with many guarantees. It's not really 
comparable to JS here.

JS extended with block-lambdas has no way to force downward-funarg-only 
contract on functions called with block-lambda arguments. And indeed, 
nothing goes wrong if those block-lambdas escape via the heap and are 
called after the enclosing function's activation, which passed the 
block-lambda down, has returned. Only if the block-lambda does a control 
effect that would propagate to the enclosing function's activation is 
there a dynamic error.

JS is a dynamic language. When you write "it should only be allowed", 
are you seriously proposing a checkable syntax and static check of some 
kind? How would that work?

(Aside: I wish I had used "fn" instead of "function" in 1995!)

/be

> François REMY <mailto:fremycompany_pub at yahoo.fr>
> January 20, 2012 1:38 PM
> Just to add weight to my previous mail, you may find it interesting to 
> notice that my proposed syntax match nearly exactly the proposed 
> syntax of the new Mozilla-editored Rust programming language: 
> http://doc.rust-lang.org/doc/tutorial.html#closure-compatibility
>
>    call_twice({|| "I am a stack closure; });
>
>    call_twice(fn@() { "I am a boxed closure"; });
>
> It confirms my feeling about {|| ...}: it should only be allowed in a 
> context where the function still exists; it's a way to return the 
> control back to the calling function when you need to call a 
> "callback-able" function for some reason. At every other place, you 
> should use 'normal' closures (the language-agnostic equivalent of 
> ECMAScript functions), for which we should have a simplified syntax 
> (aka syntaxic sugar). I don't bother if it has to start by @, #, %, µ, 
> § or anyting else, but I feel strongly about the fact we need it.
>
> Now, I think everyone got my point, I leave the final discussion to 
> group members. But, at least, my message was sent. ;-)
>
> Best regards,
> François
>
> François REMY <mailto:fremycompany_pub at yahoo.fr>
> January 19, 2012 12:19 PM
> It may be just a personnal taste, but I've to agree the current 
> proposal (#() ...) seems very appealing to me. I did not respond to 
> your mail proposing to use the Arrow syntax because it seems obscure 
> to me. The distinction between "normal" and "fat" arrow is thin, does 
> not make sense. You either need a function-object (which doesn't have 
> 'this' mapping, has expandos) or a local-function (which has 'this' 
> mapping, just need to be a [Call] target). If you need the first, you 
> need a traditionnal function since you need something not-frozen that 
> can be added to objects as a property at a later time. If you want 
> 'this' mapping, you need something that only makes sense in a local 
> context.
>
> Additionnaly, the arrow syntax is illogical. You usually say "I want a 
> function of (X,Y) which returns X+Y" or "I want to transform X in 
> X.toString", not "From X, I want to get X.toString()".
>
> Freezing a local function seems as acceptable to me as it seemed to 
> others. A LF should only be used in a controlled context where the 
> function itself is just used as a function, not an object. But if it's 
> not acceptable to other members, I'm not against a @(x) syntax that 
> does not offer frozen functions (but I think it's a missed 
> optimization opportunity). The point about Conditionnal Compiling in 
> IE is not valid anymore since Microsoft has deleted HTML Conditionnal 
> Comments because they were not standards (even if they were used a 
> lot), so I don't think the obscure and fewly used JScript CC are meant 
> to stay, especially if it hurts another proposal.
>
> In my view of the thing, a local function should be used as a function 
> in the mathematical sense of the term: you give a parameter, it 
> returns its image by the function.
>
> The cases we are trying to solve:
>
>    var inc=#(x) x+1;
>
>    array.map(#(x) x.toString());
>
>    array.filter(#(x) isValid(x));
>
>    array.map(#(x) {
>        while(x.previousSibling) x=x.previousSibling;
>        return x;
>    });
>
> For example, I don't see this as a good use-case of a LocalFunction :
>
>    ...
>    refreshLayout: function(e) {
>        ...
>        requestAnimationFrame(#(e) this.refreshLayout(e));
>    }
>    ...
>
> It should be a block lambda instead, because it's meant to 'continue' 
> the current function in a sort of async while(true) loop.
>
>    ...
>    refreshLayout: function(e) {
>        ...
>        requestAnimationFrame({|e| this.refreshLayout(e) });
>    }
>    ...
>
> For all of the use cases where a "mathematical function" is requied, 
> you just need some valid [Call]-able item. You will never add expandos 
> on an function you don't know (ie that you received as a parameter). 
> You'll wrap it before, if you really need that. If you want the full 
> flexibility of a function-as-an-object, it means you need a 'true 
> function'; LF are not meant to replace functions in the long run, they 
> are made to serve the case where you want a short, action-related, 
> contextual function. That means 'this' binding, if needed, just like 
> it's in languages like dotNET.
>
> However, I would like to hear more about the specific reasons that led 
> Arv and Alex think a LF should not be frozen.
>
> Regards,
> François
>
>
>
> PS: The synax I speak about for LocalFunctions would be:
>
> <LocalFunctionExpression>:
>    '#(' <argument-list> ')' <expression>
>    or
>    '#(' <argument-list> ') {' <statements>* '}'
>
> They would be 'bound-this' if there's a 'this' in their body, but can 
> be left unbounded if there's no since it has no visible effet. If they 
> don't reference variables of a scope, they should not use reference 
> scope and may be reused accross function calls.
>
>
>
>
> -----Message d'origine----- From: Brendan Eich
> Sent: Thursday, January 19, 2012 8:27 PM
> To: Axel Rauschmayer ; Andreas Rossberg
> Cc: François REMY ; Oliver Hunt ; es-discuss Steen
> Subject: Re: Block lambda is cool, its syntax isn't
>
> Axel Rauschmayer <mailto:axel at rauschma.de>
> January 19, 2012 9:31 AM
>
> Rationale: wouldn’t freezing by default be OK for 98% of the cases? If
> you want anything else, you can use a traditional function. Then the
> above syntax as the only function shorthand would be OK.
>
>
> First, #(params) { body } was proposed by Arv and Alex:
>
> http://wiki.ecmascript.org/doku.php?id=strawman:shorter_function_syntax
>
> Arv and Alex feel strongly that the shorter function syntax (anything
> shortening 'function' syntax) must not freeze by default.
>
> There was lack of clarity about whether completion value as implicit
> return value was part of the proposal. If so, controvery, since there is
> a completion value leak hazard. TC39 seems to agree the solution there
> is something with different look & feel, such as block-lambdas.
>
> But, making a one-char grawlix shorthand for 'function' while still
> requiring 'return' is not considered enough of a shorthand. A possible
> cure here is to support an alternative body syntax: #(params) expr.
> However, this inverts precedence if done naively. It also runs into
> trouble trying to prefer an object literal over a block statement. I've
> worked on both of these in the context of
>
> http://wiki.ecmascript.org/doku.php?id=strawman:arrow_function_syntax
>
> This superseded shorter_function_syntax, but ran into grammatical issues
> that have vexed it.
>
> But notice that throughout this, no one advancing a proposal advocated
> freezing by default. JS developers use function objects as mutable
> objects. Not just to set .prototype, also to decorate with ad-hoc and
> meta-data properties. Freezing is not wanted by default.
>
> I agree that for block-lambdas it's easier to say "freeze by default".
> For merely "shorter function syntax", no. Functions are mutable objects
> by default in JS. This matters for minifiers, which may not be able to
> see all the mutations but would love to use shorter syntax for
> 'function' syntax, blindly.
>
> /be
>
> Brendan Eich <mailto:brendan at mozilla.com>
> January 19, 2012 11:27 AM
> Axel Rauschmayer <mailto:axel at rauschma.de>
> January 19, 2012 9:31 AM
>
> Rationale: wouldn’t freezing by default be OK for 98% of the cases? If 
> you want anything else, you can use a traditional function. Then the 
> above syntax as the only function shorthand would be OK.
>
>
> First, #(params) { body } was proposed by Arv and Alex:
>
> http://wiki.ecmascript.org/doku.php?id=strawman:shorter_function_syntax
>
> Arv and Alex feel strongly that the shorter function syntax (anything 
> shortening 'function' syntax) must not freeze by default.
>
> There was lack of clarity about whether completion value as implicit 
> return value was part of the proposal. If so, controvery, since there 
> is a completion value leak hazard. TC39 seems to agree the solution 
> there is something with different look & feel, such as block-lambdas.
>
> But, making a one-char grawlix shorthand for 'function' while still 
> requiring 'return' is not considered enough of a shorthand. A possible 
> cure here is to support an alternative body syntax: #(params) expr. 
> However, this inverts precedence if done naively. It also runs into 
> trouble trying to prefer an object literal over a block statement. 
> I've worked on both of these in the context of
>
> http://wiki.ecmascript.org/doku.php?id=strawman:arrow_function_syntax
>
> This superseded shorter_function_syntax, but ran into grammatical 
> issues that have vexed it.
>
> But notice that throughout this, no one advancing a proposal advocated 
> freezing by default. JS developers use function objects as mutable 
> objects. Not just to set .prototype, also to decorate with ad-hoc and 
> meta-data properties. Freezing is not wanted by default.
>
> I agree that for block-lambdas it's easier to say "freeze by default". 
> For merely "shorter function syntax", no. Functions are mutable 
> objects by default in JS. This matters for minifiers, which may not be 
> able to see all the mutations but would love to use shorter syntax for 
> 'function' syntax, blindly.
>
> /be
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
> Axel Rauschmayer <mailto:axel at rauschma.de>
> January 19, 2012 9:31 AM
>
> Rationale: wouldn’t freezing by default be OK for 98% of the cases? If 
> you want anything else, you can use a traditional function. Then the 
> above syntax as the only function shorthand would be OK.
>
> -- 
> Dr. Axel Rauschmayer
> axel at rauschma.de <mailto:axel at rauschma.de>
>
> home: rauschma.de <http://rauschma.de>
> twitter: twitter.com/rauschma <http://twitter.com/rauschma>
> blog: 2ality.com <http://2ality.com>
>
> Brendan Eich <mailto:brendan at mozilla.com>
> January 19, 2012 9:25 AM
>
> I'm not sure what you mean. I proposed this a while ago ("Harmony of 
> My Dreams") but we don't want frozen by design, and without the # the 
> result is ambiguous without restricted productions, and hazardous on 
> that account.
>
> The idea that any grawlixy preifx will do is false. Hash is wanted for 
> consistent freeze/seal prefixing. Arrow is better and putting it at 
> the front solves the grammar problems with arrow function syntax as 
> current drafted.
>
> /be
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>


More information about the es-discuss mailing list