On May 23, 2011, at 9:04 AM, Kam Kasravi wrote:

> In the block lambda strawman examples, the surprise 
> is the use of return (and other goto constructs like break). At least in 
> similar discussions related 
> to closures in java, Neal Grafter

(Gafter)


> suggests that return and other control constructs not be allowed 
> (http://gafter.blogspot.com/2006/08/tennents-correspondence-principle-and.html)
>  due to TCP.

That's not quite a solution: you can indeed then factor out the guts of a 
closure immediately or downward-funarg-ly (sic) invoked -- but you can't factor 
code the other direction without losing expressiveness at the statement level.


> I assume this is also why var is being excluded in the strawman.

No, var is worse because it hoists to top of function body. Strictly different 
and harder compared to break/continue loop/switch targeting (which falls out 
for free with proper Completion type usage), and also compared to return (no 
hoisting).


> Given the impact to the grammar to exclude var,

Trivial. Can be done a la the "NoIn" productions but better if we do it with 
prose. Not a big deal, IMHO.


> would this constraint be compile time checked?

Yes, |var| would be forbidden in block-lambdas by early error.


> Would grammar  constraints like no var be semantically checked by 
> implementors or folded into the grammar formally?

See above; not a big deal, up to specificiers.


> The latter would suggest a production rule other than StatementList*, where 
> VariableStatement would be excluded...

That's too duplicative. The NoIn productions are too. We could have 
parameterized productions, or use prose. This is a sideshow, though.

I don't agree with banning control statements in blocks, in any event.

/be

> 
> On May 23, 2011, at 6:57 AM, Brendan Eich <bren...@mozilla.com> wrote:
> 
>> On May 22, 2011, at 10:15 PM, Kam Kasravi wrote:
>> 
>>> Is this valid?
>>> 
>>> function Person(a) {
>>>   this.age = a;
>>> }
>>> Person.prototype.myage = {|| this.age};
>> 
>> Block-lambda, per Tennent's Correspondence Principle as cited, uses the same 
>> this as if you moved the code inside the {|| ... } outside. This is so expr 
>> is equivalent to {|| expr }(). JS hackers do not see function () { ... } so 
>> should not expect this to change meaning.
>> 
>> (For this reason among others, block-lambdas have no [[Construct]] internal 
>> method. Same as for built-in functions in ES1-5.)
>> 
>> So this is not going to do what you want below:
>> 
>>> function info(myage) {
>>>   console.log('my age is '+myage());   
>>> }
>>> info(new Person(10).myage);
>>> info(new Person(12).myage);
>> 
>> Enclosing the block-lambda within the constructor works:
>> 
>> function Person(a) {
>>   this.age = a;
>>   this.myage = {|| this.age};
>> }
>> 
>> Note that in this case, unlike the case with a function expression instead 
>> of the block-lambda, the implementation can optimize aggressively: no other 
>> this can be bound dynamically in any subsequent call via new 
>> Person(10).myage() or myage() in info. This is a stronger guarantee than if 
>> Person used
>> 
>>   this.myage = function () { return this.age; }.bind(this);
>> 
>> in the absence of aggressive static analysis (without which, who knows what 
>> bind means at compile time)?
>> 
>> The full closure pattern works too, of course:
>> 
>> function Person(a) {
>>   return {get age() { return a; }, myage: {|| a}};
>> }
>> 
>> 
>> but you have to commit to accessors.
>> 
>> One last note: freezing and joining (see # usage in 
>> http://wiki.ecmascript.org/doku.php?id=strawman:arrow_function_syntax 
>> referencing http://wiki.ecmascript.org/doku.php?id=strawman:const_functions) 
>> do not enable much more optimization in this constructor pattern, however 
>> you do it. Whether closing over this or the parameter a, the joined 
>> block-lambda (or function) identity cannot join across the Person closure 
>> boundary.
>> 
>> (I did not make block-lambdas implicitly frozen and joined since some on 
>> TC39 and in the community object to that kind of change without opt-in 
>> syntax, and because it doesn't help much, given the change to make this a 
>> lexical "upvar".)
>> 
>> So block-lambdas are not going to solve the "bound method" cost problem in 
>> JS. For that, you need a class proposal that automatically binds methods to 
>> the receiver while at the same time disallowing any kind of dynamic 
>> inheritance. ES4 after ActionScript 3 had this; Java etc. do too of course.
>> 
>> Does JS really need it, vs. the prototypal function-valued properties as 
>> methods pattern? In any event, nothing block-lambdas or any other 
>> this-capturing form can fix by themselves.
>> 
>> /be
>> 

_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to