Re: Making super work outside a literal?

2011-06-23 Thread Brendan Eich
On Jun 22, 2011, at 4:02 PM, Axel Rauschmayer wrote:

 From: Brendan Eich bren...@mozilla.com
 Date: June 23, 2011 0:21:17 GMT+02:00
 
 Is there no per-call cost whatsoever to adding static super?
 
 No, it's static -- an internal property of the function object set once on 
 creation and (in my view) never changed thereafter unless unobservably 
 (Allen's point about optimizing Object.defineMethod when handing off an 
 otherwise-useless function expression).
 
 
 How does a function get access to its properties? Doesn’t the ability to 
 access thisFunction incur any costs? I would expect static super to work as 
 follows:
 
 var Sub = Super | {
 foo: function me(x) {
 me.super.foo.call(this, x);
 }
 }
 
 Does the named function expression cost nothing here?

This is entirely beside the point.

Dynamic |super| as Sean proposes requires *every call site* to pass the |here| 
parameter or something derived from it, no way around that.

Paying for 'super' if you use it, buying by the yard, is not a problem.

Making *every function call* in the language slow, increasing register 
pressure, etc. -- absent aggressive inference to identify callees and 
specialize call sites to them (inlining VMs do this but it can backfire, so 
there will be a default case that can't do this) -- is a big problem.

/be

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


Re: Analog to Object.getPropertyDescriptor() for *changing* a property value?

2011-06-23 Thread Brendan Eich
On Jun 22, 2011, at 3:55 PM, Axel Rauschmayer wrote:

 You should not in general mutate shared prototype state via one of N 
 delegating objects. It leads to trouble.
 
 What’s the difference to a global variable?

The list is long.

How about this? You have a bunch of local variables in various functions 
referencing different objects. But by some obscure yet legal means you use one 
such reference to mutate the prototype object they share in common, so all the 
others appear to be mutated too.

This is not inherently evil, but it's usually a bug. Usually the other 
different objects do not wish to be mutated so indirectly, and the users of 
their properties (own and delegated) in those various functions may not be 
prepared for such a change.

Consider monkey-patching. You want to add value to a shared prototype, but you 
might break for-in loops. Ok, that can be solved with ES5 Object.defineProperty 
-- but not if the mutation breaks some other invariant.

It's occasionally useful to do AOP on shared prototypes. My point is that you 
ought to address them directly by their true names (Array.prototype, e.g.; not 
Object.getPrototypeOf(someArray)).

/be

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


Re: Making super work outside a literal?

2011-06-23 Thread Allen Wirfs-Brock

On Jun 23, 2011, at 7:04 AM, Brendan Eich wrote:

 On Jun 22, 2011, at 4:02 PM, Axel Rauschmayer wrote:
 
 
 
 
 Does the named function expression cost nothing here?
 
 This is entirely beside the point.
 
 Dynamic |super| as Sean proposes requires *every call site* to pass the 
 |here| parameter or something derived from it, no way around that.
 
 Paying for 'super' if you use it, buying by the yard, is not a problem.
 
 Making *every function call* in the language slow, increasing register 
 pressure, etc. -- absent aggressive inference to identify callees and 
 specialize call sites to them (inlining VMs do this but it can backfire, so 
 there will be a default case that can't do this) -- is a big problem.
 
 /be

If you don't have actual implementation experience with dynamic languages I 
think you guys will just have to take Brendan's and my word for this. Dynamic 
super would have unacceptable overhead on every function call. 

Dynamic super may be conceptually slightly cleaner conceptually in that it 
eliminates the need for Object.defineMethod.  However, the cost is unacceptably 
high.

Pragmatically, the choice is between static super and no super. Insisting on 
dynamic super just pushes the discussion in the no super direction. 

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


Re: Analog to Object.getPropertyDescriptor() for *changing* a property value?

2011-06-23 Thread Allen Wirfs-Brock

On Jun 21, 2011, at 9:50 PM, Axel Rauschmayer wrote:

 That sounds like the opposite argument you are making with regard to the 
 hypothetical |here|:
 
 BTW I do not agree we can or should try to reserve 'here' or expose the 
 method's home object -- that breaks abstractions built using prototypes. 
 'super' does not, because it always goes to the [[Prototype]] of the object 
 in which the method was defined.
 
 The prototype seems to be the best location for shared data (such as the 
 number of instances of a class). Wouldn’t you also want to abstract from the 
 exact location of such a property?

Behaviorally, you shouldn't care how an object is implemented.  Whether a 
particular property is implemented as an own property or is inherited from a 
prototype is an implementation detail that should be irrelevant to client code 
that is using an object.  Such implementation details should be, at least 
conceptually, encapsulated by the object.  

If you are dynamically inspecting or modifying details of the implementation of 
an object you have moved into the realm of reflection.  Object.getPrototypeOf, 
Object.getOwnPropertyDescriptor, etc. are reflection operations.  Generally it 
is poor practice to design an object such that client code needs to enter the 
domain of reflection to interact with the object.  If client code uses these 
operations it is breaking implementation encapsulation. 

One of the reason that the reflection functions added by ES5 are defined on 
Object rather than Object.prototype is to avoid polluting the public interface 
of every object with additional reflective operations over and beyond the 
legacy ones already defined in ES1-3. Arguably, even that separation isn't 
enough as Object really is in the application layer of the system rather than 
the reflection layer.  In the long run it would be good if we could  further 
separate the reflection layer by migrating to a Mirrors-based reflection model. 
 See my series of blogs post about Mirrors for JavaScript 
http://www.wirfs-brock.com/allen/posts/228 for more details.

We probably still need to add some reflection methods to Object.  defineMethod 
is one strong candidate.  However, we really should be quite careful about what 
goes there as it is just too easy to use such Object.* functions to violate an 
object's implementation encapsulation.

Allen

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


Re: Analog to Object.getPropertyDescriptor() for *changing* a property value?

2011-06-23 Thread David Bruant

Hi,

In a the provided example, you assign a value. Can't you just use a 
getter/setter pair on the prototype chain? It sounds like it would solve 
your use case (without the syntax sugar). On ES5 - 8.12.5 step 4  5, 
the prototype chain is climbed to look up for an accessor and if there 
is a setter (anywhere on the prototype chain), this setter is called. 
Combined with the fact that a getter naturally do the same thing for 
getters, you have your way to change a value directly on the prototype 
chain.
Of course, if you want to change the property descriptor on the 
prototype chain, none of what I said apply.


David


Le 21/06/2011 17:24, Axel Rauschmayer a écrit :

As a loose analog to the prototype-chain-traversing getPropertyDescriptor(), I 
would still like to have something that allows one to easily *change* 
properties higher up the prototype chain (e.g. to use a prototype to share 
state).

Maybe it would be enough to just have Object.getDefiningObject(obj, propName):
http://www.mail-archive.com/es-discuss@mozilla.org/msg06652.html

But I can also imagine syntactic sugar:
 obj.foo := abc
desugars to
 Object.getDefiningObject(obj, foo).foo = abc

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


Re: Analog to Object.getPropertyDescriptor() for *changing* a property value?

2011-06-23 Thread Axel Rauschmayer
I guess my argument goes like this:
- If the prototype of an instance loosely corresponds to a class, why shouldn’t 
we have class variables/class state?
- If the location for reading data is abstracted over, why isn’t the location 
for writing data?

On Jun 23, 2011, at 12:29 , Allen Wirfs-Brock wrote:

 
 On Jun 21, 2011, at 9:50 PM, Axel Rauschmayer wrote:
 
 That sounds like the opposite argument you are making with regard to the 
 hypothetical |here|:
 
 BTW I do not agree we can or should try to reserve 'here' or expose the 
 method's home object -- that breaks abstractions built using prototypes. 
 'super' does not, because it always goes to the [[Prototype]] of the object 
 in which the method was defined.
 
 The prototype seems to be the best location for shared data (such as the 
 number of instances of a class). Wouldn’t you also want to abstract from the 
 exact location of such a property?
 
 Behaviorally, you shouldn't care how an object is implemented.  Whether a 
 particular property is implemented as an own property or is inherited from a 
 prototype is an implementation detail that should be irrelevant to client 
 code that is using an object.  Such implementation details should be, at 
 least conceptually, encapsulated by the object.  
 
 If you are dynamically inspecting or modifying details of the implementation 
 of an object you have moved into the realm of reflection.  
 Object.getPrototypeOf, Object.getOwnPropertyDescriptor, etc. are reflection 
 operations.  Generally it is poor practice to design an object such that 
 client code needs to enter the domain of reflection to interact with the 
 object.  If client code uses these operations it is breaking implementation 
 encapsulation. 
 
 One of the reason that the reflection functions added by ES5 are defined on 
 Object rather than Object.prototype is to avoid polluting the public 
 interface of every object with additional reflective operations over and 
 beyond the legacy ones already defined in ES1-3. Arguably, even that 
 separation isn't enough as Object really is in the application layer of the 
 system rather than the reflection layer.  In the long run it would be good if 
 we could  further separate the reflection layer by migrating to a 
 Mirrors-based reflection model.  See my series of blogs post about Mirrors 
 for JavaScript http://www.wirfs-brock.com/allen/posts/228 for more details.
 
 We probably still need to add some reflection methods to Object.  
 defineMethod is one strong candidate.  However, we really should be quite 
 careful about what goes there as it is just too easy to use such Object.* 
 functions to violate an object's implementation encapsulation.
 
 Allen
 

-- 
Dr. Axel Rauschmayer

a...@rauschma.de
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



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


Re: Analog to Object.getPropertyDescriptor() for *changing* a property value?

2011-06-23 Thread Axel Rauschmayer
 How about this? You have a bunch of local variables in various functions 
 referencing different objects. But by some obscure yet legal means you use 
 one such reference to mutate the prototype object they share in common, so 
 all the others appear to be mutated too.
 
 This is not inherently evil, but it's usually a bug. Usually the other 
 different objects do not wish to be mutated so indirectly, and the users of 
 their properties (own and delegated) in those various functions may not be 
 prepared for such a change.

So you are mainly worried about mutating methods? My main concern is 
encapsulation: If you have class methods, I would want to give them the option 
of having class state. I want the same rules that hold for the object level 
(state + behavior) to hold for the meta-object level.

 Consider monkey-patching. You want to add value to a shared prototype, but 
 you might break for-in loops. Ok, that can be solved with ES5 
 Object.defineProperty -- but not if the mutation breaks some other invariant.

I would probably never use for-in loops in ES.next.

 It's occasionally useful to do AOP on shared prototypes. My point is that you 
 ought to address them directly by their true names (Array.prototype, e.g.; 
 not Object.getPrototypeOf(someArray)).


Right, the latter looks really bad. I would rely that the same kind of unique 
name that took me to a class method (via this) will also take me to a class 
variable (also via this). If I invoke the method via this, e.g. 
Array.prototype.myClassMethod(), then this.myClassVariable would *still* work.

-- 
Dr. Axel Rauschmayer

a...@rauschma.de
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



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


Re: Analog to Object.getPropertyDescriptor() for *changing* a property value?

2011-06-23 Thread Axel Rauschmayer
There are indeed a few ways around this:
Naming the prototype, using an array with a single element, etc.

On Jun 23, 2011, at 13:19 , David Bruant wrote:

 Hi,
 
 In a the provided example, you assign a value. Can't you just use a 
 getter/setter pair on the prototype chain? It sounds like it would solve your 
 use case (without the syntax sugar). On ES5 - 8.12.5 step 4  5, the 
 prototype chain is climbed to look up for an accessor and if there is a 
 setter (anywhere on the prototype chain), this setter is called. Combined 
 with the fact that a getter naturally do the same thing for getters, you have 
 your way to change a value directly on the prototype chain.
 Of course, if you want to change the property descriptor on the prototype 
 chain, none of what I said apply.
 
 David
 
 
 Le 21/06/2011 17:24, Axel Rauschmayer a écrit :
 As a loose analog to the prototype-chain-traversing getPropertyDescriptor(), 
 I would still like to have something that allows one to easily *change* 
 properties higher up the prototype chain (e.g. to use a prototype to share 
 state).
 
 Maybe it would be enough to just have Object.getDefiningObject(obj, 
 propName):
 http://www.mail-archive.com/es-discuss@mozilla.org/msg06652.html
 
 But I can also imagine syntactic sugar:
 obj.foo := abc
 desugars to
 Object.getDefiningObject(obj, foo).foo = abc
 

-- 
Dr. Axel Rauschmayer

a...@rauschma.de
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



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


Re: Analog to Object.getPropertyDescriptor() for *changing* a property value?

2011-06-23 Thread David Bruant

Here is a code snippet:

var p = {};
(function(){
  var a;
  Object.defineProperty(p, 'a', {get:function(){return a;}, 
set:function(v){a = v;}});

})();

var o1 = Object.create(p);
var o2 = Object.create(p);

o1.a = 1;
console.log(o1.a, o2.a); // 1 1
o2.a = 37;
console.log(o1.a, o2.a); // 37 37

'a' is an own property neither of o1 nor o2. (Firefox may say the 
opposite, but I've been told, it's fixed and going to be released on FF 
6 or 7 [1] [2]). a value (so to say) is shared among the instances.


David

[1] https://bugzilla.mozilla.org/show_bug.cgi?id=636989
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=637994

Le 23/06/2011 13:19, David Bruant a écrit :

Hi,

In a the provided example, you assign a value. Can't you just use a 
getter/setter pair on the prototype chain? It sounds like it would 
solve your use case (without the syntax sugar). On ES5 - 8.12.5 step 4 
 5, the prototype chain is climbed to look up for an accessor and if 
there is a setter (anywhere on the prototype chain), this setter is 
called. Combined with the fact that a getter naturally do the same 
thing for getters, you have your way to change a value directly on 
the prototype chain.
Of course, if you want to change the property descriptor on the 
prototype chain, none of what I said apply.


David


Le 21/06/2011 17:24, Axel Rauschmayer a écrit :
As a loose analog to the prototype-chain-traversing 
getPropertyDescriptor(), I would still like to have something that 
allows one to easily *change* properties higher up the prototype 
chain (e.g. to use a prototype to share state).


Maybe it would be enough to just have Object.getDefiningObject(obj, 
propName):

http://www.mail-archive.com/es-discuss@mozilla.org/msg06652.html

But I can also imagine syntactic sugar:
 obj.foo := abc
desugars to
 Object.getDefiningObject(obj, foo).foo = abc

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


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


Re: imperative vs functional APIs or: how to work with constant objects?

2011-06-23 Thread Claus Reinke

Javascript data structure operations: some of the APIs are imperative,
some are functional, some are mixed. Having functional equivalents
to all imperative data structure operations is necessary to support
expression-oriented programming over constant data structures.

imperative here refers to operations that are designed to be used as
statements, changing inputs by side-effect, while functional refers to
operations designed to be used as expressions, leaving their inputs
unchanged. ..


Hi Claus, interesting idea. Given

The idea of {x: a, y: b, ...: c} – record extension and row
capturehttp://successor-ml.org/index.php?title=Functional_record_extension_and_row_capture
–
for structuring and destructuring comes to mind, but ES objects are a
different animal compared to ML records. For example, which properties of 
c are

copied into the object being initialized by {x: a, y: b, ...: c}?
enumerable? own? etc.

(from 
http://wiki.ecmascript.org/doku.php?id=harmony:destructuring#issues)


you could say

   const older_obj = { age: 2, ...: obj };

But as the note says, there are a bunch of open questions that need to be
settled before this becomes a serious candidate. We should examine how 
this

interacts with other aspects of extended object literals.


Hi Mark,

thanks for the pointer.

Yes, there used to be a large body of literature just on the various
ways of factoring a record operations API, mostly driven by their
use for semantics of object-oriented language variations and by
their type system difficulties ('record calculi', 'semantics of
inheritance/oo', 'typing record concatenation', ..).

Record/object extension is one of the recurring ideas, and since
it is based on record/object literals + a base record/object, most
of the design choices follow from the extended object literals.

My immediate concern is simply: given the choices already made
for Javascript object operations, why don't we have a complete set
of operations for both in-place and copying updates? The current
situation at the object level is as if JS only had '+=' and '-=', but
not '+' and '-', at the level of numbers.

As for the set of operations, JS has already chosen that updating
a non-existing property extends the object, so update and extension
are mixed in one operation. There is a separate operation for removing
properties and there are tests for the existence of properties, both
locally and in the prototype chain. If there were functional equivalents
to the imperative base operations

   obj.prop = value;
   delete obj.prop;

then one could build more complex operations from there, instead
of from scratch. delete already returns the object, but assignment
returns the value, and overloading delete to produce an object copy
if the input object is frozen would be confusing, so we need new
syntax, and object extension with extended object literals could do.

Assuming that the extended object is copied as is, modified as
specifiable by the extended object literal syntax, I'd assume

   { prop : value; ...: obj }

to be a (shallow) copy of obj, identical (including prototype and
meta properties such as frozen/configurable/..) in all but prop.

If I don't want to copy prototype or meta-properties, I'd need
to use records instead of objects, or get some help from the
extended object literal syntax.

But one shouldn't try to fit everything into the object literal
syntax, either - once it is accepted that copying objects is useful,
there could be an Object.filter operation, eg, to filter out
properties based on their meta-properties (enumerable, own, ..):

   Object.filter(predicate,obj)

would return a (shallow) copy of obj with properties filtered
according to some predicate function.

To avoid an additional operator for functional delete, one might
add a delete directive to extended object literal syntax, and have

   { delete prop; ...: obj}

be a (shallow) copy of obj, identical in all but prop.

Wouldn't that be sufficient as a baseline? If not, what is missing?

Is extended object literal syntax capable of handling this slightly
extended range of use? Btw, should there be a way to un-freeze
object copies (typical application is to make a non-frozen copy
of a frozen array, update it incrementally and in-place in a loop,
then freeze the resulting array copy for further use)?

In sum, copying object modifications are useful for programmers,
and taking them into consideration might ease the constraints
for ES language design (not everything has to fit into the simple
in-place update all-permitted-or-all forbidden scheme - copying
updates offer a third option).

Claus


The standard APIs for these fundamental operations are imperative
and so are not available on frozen objects (this also applies to the
record strawman, for instance).

How does one achieve the effects of these operations on frozen
objects, by creating modified copies? For an expression-oriented style of
programming where no object is ever modified in place, it 

Re: Making super work outside a literal?

2011-06-23 Thread Allen Wirfs-Brock

On Jun 23, 2011, at 12:31 PM, Axel Rauschmayer wrote:

 This is entirely beside the point.
 
 Dynamic |super| as Sean proposes requires *every call site* to pass the 
 |here| parameter or something derived from it, no way around that.
 
 Paying for 'super' if you use it, buying by the yard, is not a problem.
 
 Making *every function call* in the language slow, increasing register 
 pressure, etc. -- absent aggressive inference to identify callees and 
 specialize call sites to them (inlining VMs do this but it can backfire, so 
 there will be a default case that can't do this) -- is a big problem.
 
 I believe you about the dynamic super. I can summarize my question as follows:
 - Making super or current object available to a function incurs costs.
If it is statically bound (via a [[Super]]  or [[Current]] internal property 
then there is only a cost (and a small one) on actual accesses of super.  EG,
   Object.defineMethod(obj,'foo, function() {return super.foo() /*cost to 
access [[Super]] + cost to access this */});

If dynamically bound (on each property lookup of the method)  then there is a 
cost on every function call to pass the current object reference to the 
function invocation.  This cost is in addition to the const of passing thethis 
reference.

 - Making current function available to a function does not incur costs? 
 This is *not* an extra parameter, then?

the current function is made available via the function name in a function 
declaration:
  var q= -1;
  Object.defineMethod(objfoo,function bar(a,b,c) {return q*bar.length /* 
returns -3 */});

bar is a lexically scoped binding just like q.  No per call perimeters are 
involved.  The cost to access bar is approximately the same as the cost of 
accessing q (exact costs subject to details of how lexically scoped access is 
implemented)

Allen


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


Re: Making super work outside a literal?

2011-06-23 Thread Sean Eagan
On Thu, Jun 23, 2011 at 4:56 AM, Allen Wirfs-Brock
al...@wirfs-brock.com wrote:
 If you don't have actual implementation experience with dynamic languages I
 think you guys will just have to take Brendan's and my word for this.

I now understand and fully agree with your performance arguments
against dynamic super.  However, I still believe that the dynamic
super semantics are largely superior to the static super semantics.

Fortunately, I think the dynamic super semantics can be simulated via
static super, thus yielding the best of both approaches!

Here's what I propose:

Terminology:

super function - a function that uses |super|
super delegate function - A function which delegates to a super
function stored in its [[SuperFunction]] internal property, passing a
|super| binding stored in its [[Super]] internal property.

Semantics:

When a super function is assigned as a method or accessor getter or
setter either via an object literal, Object.defineProperty or direct
assignment, a super delegate function is created and assigned instead
whose [[SuperFunction]] internal property is the super function being
assigned, and whose [[Super]] internal property is the [[Prototype]]
internal property of the object being assigned to.

When a super delegate function is subsequently accessed from an
object, e.g. o.methodThatUsesSuper or
Object.getOwnPropertyDescriptor(o,
accessorWithGetterOrSetterThatUsesSuper), this resolves to the
[[TargetFunction]] internal property of the super delegate function.

When a super function is called directly, e.g. superFunction() or
superFunction.call(this), |super| is resolved as the [[Prototype]]
internal property of the |this| of the call.

When a super delegate function is called, e.g.
o.methodThatUsesSuper(), o.accessorWithGetterThatUsesSuper, or
o.accessorWithSetterThatUsesSuper = foo, |super| is bound to the
super delegate function's [[Super]] internal property.

The equivalence class of a super function in  == and === consists of
the super function and all of its corresponding super delegate
functions, to illustrate:

let f = function(){return super.x},
o1 = {method: f},
o2 = Object.create(null, {method: {get: f}});
assert(f === o1.method); // true
assert(o1.method === Object.getOwnPropertyDescriptor(o2, method).get); // true

Thus, the static super implementation is completely abstracted from
the user, and they benefit from the full dynamic super semantics!

I'm sure there are still details to work out, but it seems quite
promising to me.

Cheers,
Sean Eagan
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Making super work outside a literal?

2011-06-23 Thread Allen Wirfs-Brock

On Jun 23, 2011, at 2:56 PM, Axel Rauschmayer wrote:

 - Making current function available to a function does not incur costs? 
 This is *not* an extra parameter, then?
 
 the current function is made available via the function name in a function 
 declaration:
 var q= -1;
 Object.defineMethod(objfoo,function bar(a,b,c) {return q*bar.length /* 
 returns -3 */});
 
 bar is a lexically scoped binding just like q.  No per call perimeters are 
 involved.  The cost to access bar is approximately the same as the cost of 
 accessing q (exact costs subject to details of how lexically scoped access 
 is implemented)
 
 
 Isn’t bar a named function expression and won't this binding be local to 
 the expression (unlike q)? But I don’t think that changes the cost.
 

Yes, that was the reason for my final comment about the exact cost. Depending 
upon the implementation details there may be minor difference in the cost of 
accessing bar and q.  However, any such difference is likely to be small 
and of little significance.

Technically, according to the language specification, q, bar, and the 
function arguments a,b,c are in different scope contours.

Allen


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


Re: Making super work outside a literal?

2011-06-23 Thread Sean Eagan
A couple corrections below:

On Thu, Jun 23, 2011 at 9:14 AM, Sean Eagan seaneag...@gmail.com wrote:
 When a super delegate function is subsequently accessed from an
 object, e.g. o.methodThatUsesSuper or
 Object.getOwnPropertyDescriptor(o,
 accessorWithGetterOrSetterThatUsesSuper), this resolves to the
 [[TargetFunction]] internal property of the super delegate function.

[[TargetFunction]] should be [[SuperFunction]]

 The equivalence class of a super function in  == and === consists of
 the super function and all of its corresponding super delegate
 functions

Actually, it's simpler than this.  One can never obtain a reference to
a super delegate function, only call it as a method or accessor getter
or setter.

Cheers,
Sean Eagan
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Analog to Object.getPropertyDescriptor() for *changing* a property value?

2011-06-23 Thread Brendan Eich
On Jun 23, 2011, at 4:54 AM, Axel Rauschmayer wrote:

 How about this? You have a bunch of local variables in various functions 
 referencing different objects. But by some obscure yet legal means you use 
 one such reference to mutate the prototype object they share in common, so 
 all the others appear to be mutated too.
 
 This is not inherently evil, but it's usually a bug. Usually the other 
 different objects do not wish to be mutated so indirectly, and the users of 
 their properties (own and delegated) in those various functions may not be 
 prepared for such a change.
 
 So you are mainly worried about mutating methods?

No, any data property.


 My main concern is encapsulation: If you have class methods, I would want to 
 give them the option of having class state. I want the same rules that hold 
 for the object level (state + behavior) to hold for the meta-object level.

The prototype is not the class.

 
 Consider monkey-patching. You want to add value to a shared prototype, but 
 you might break for-in loops. Ok, that can be solved with ES5 
 Object.defineProperty -- but not if the mutation breaks some other invariant.
 
 I would probably never use for-in loops in ES.next.

That does not address the general problem. Please read the whole sentence 
including the part I wrote after the --.

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


Re: Making super work outside a literal?

2011-06-23 Thread Sean Eagan
Ok, sorry it took me so long, but I agree that the general idea of
Object.defineMethod is the best solution.  I think it can be improved
upon though, by adding the following:

Ability to use any property descriptor attributes when defining methods.
Ability to assign accessor getters and setters as well which use the
assigned to object as |super|.
Avoid having to add a defineMethod proxy trap.

Here are the two potential solutions I have in mind for this:

* Have Object.defineProperty create new functions with updated
[[Super]] when the value, get, or set attributes are functions
that use super.

* Add an Object.defineSuperProperty which is the same as the existing
Object.defineProperty except that it creates new functions with
updated [[Super]] when the value, get, or set attributes are
functions that use super.  It could potentially throw if no super
functions are passed.  This one may still require a
defineSuperProperty proxy trap, not sure.

Also, I wonder if there is a need for a Function.prototype.isSuper
similar to Function.prototype.isGenerator?

On Thu, Jun 23, 2011 at 10:51 AM, Allen Wirfs-Brock
al...@wirfs-brock.com wrote:

 On Jun 23, 2011, at 3:14 PM, Sean Eagan wrote:

 On Thu, Jun 23, 2011 at 4:56 AM, Allen Wirfs-Brock
 al...@wirfs-brock.com wrote:
 If you don't have actual implementation experience with dynamic languages I
 think you guys will just have to take Brendan's and my word for this.

 I now understand and fully agree with your performance arguments
 against dynamic super.  However, I still believe that the dynamic
 super semantics are largely superior to the static super semantics.

 Fortunately, I think the dynamic super semantics can be simulated via
 static super, thus yielding the best of both approaches!

 Here's what I propose:

 Terminology:

 super function - a function that uses |super|
 super delegate function - A function which delegates to a super
 function stored in its [[SuperFunction]] internal property, passing a
 |super| binding stored in its [[Super]] internal property.

 so every super function still requires an implicit super parameter


 Semantics:

 When a super function is assigned as a method or accessor getter or
 setter either via an object literal, Object.defineProperty or direct
 assignment,
 this would add overhead to every [[Put]].  a test to see if the value is a 
 super function.  The way to avoid the test would be defer the test until the 
 value of the property was retrieved  (first time only perhaps. This is 
 essentially the same as  the dynamic super implementation strategy of 
 conditionally only passing the current object to a super function.  So, you 
 have traded overhead on ever call for over head on every [[Put]].  [[Put]]'s 
 probaby occur less often than [[Call]]'s but may still be too much.

 a super delegate function is created and assigned instead
 whose [[SuperFunction]] internal property is the super function being
 assigned, and whose [[Super]] internal property is the [[Prototype]]
 internal property of the object being assigned to.

 When a super delegate function is subsequently accessed from an
 object, e.g. o.methodThatUsesSuper or
 Object.getOwnPropertyDescriptor(o,
 accessorWithGetterOrSetterThatUsesSuper), this resolves to the
 [[TargetFunction]] internal property of the super delegate function.

 I believe you are saying that upon property revival, a super delegate 
 function reference is replaced with the value of its [[SuperFunction]].  This 
 means there is an additional check (is the property value a super delegate 
 function) on every [[Get]].


 When a super function is called directly, e.g. superFunction() or
 superFunction.call(this), |super| is resolved as the [[Prototype]]
 internal property of the |this| of the call.

 How does it know it is being called directly?

 This seems to be the primary thing this approach adds to simple static super. 
  Why is this really important?  Is there a common usage case that requires 
 this.  I don't believe it has been addressed by other OO languages.

 When a super delegate function is called, e.g.
 o.methodThatUsesSuper(), o.accessorWithGetterThatUsesSuper, or
 o.accessorWithSetterThatUsesSuper = foo, |super| is bound to the
 super delegate function's [[Super]] internal property.

 in other words, the super delegate function calls the super function passing 
 the value of its [[Super]] as the implicit super parameter



 The equivalence class of a super function in  == and === consists of
 the super function and all of its corresponding super delegate
 functions, to illustrate:

 let f = function(){return super.x},
    o1 = {method: f},
    o2 = Object.create(null, {method: {get: f}});
 assert(f === o1.method); // true
 assert(o1.method === Object.getOwnPropertyDescriptor(o2, method).get); // 
 true

 Thus, the static super implementation is completely abstracted from
 the user, and they benefit from the full dynamic super semantics!

 At the expense of additional runtime 

block-lambda revival

2011-06-23 Thread Marc Harter
Peter Michaux encouraged me to write my thoughts on es-discuss so here I am.

Out of the various new function syntaxes proposed ( -, #, {||} ) I
have really taken a liking to the block-lambda revival strawman.  I
think in general they all address similar wishes (e.g. implicit
return, this, shorter). I prefer the block-lambda because of some use
cases:

let a = [1,2,3,4];
let b = a.reduce((a,b) - a + b) // didn't see an example for this one
assuming this is how it looks
let b = a.reduce {|a,b| a + b} // less cluttery, fn bound by braces,
couple characters less to type

Self executing function expressions

(- {
  // multi-line
}())

{||
  // multi-line -- i'm assuming there wouldn't need to be parens
around the whole thing because block lambdas are expressions not
statements (is this the case with arrow?)
}()

I like block-lambda because:

  1. From my understanding braces aren't going away, lets just embrace
them (use them as part of the syntax)
  2. Arrow gets too bulky with braces (although worked good for CoffeeScript)
  3. Seems to be terse yet clear
  4. Encloses the function

It may be nice to have side by side comparisons of the different
proposals doing the same operation.

Anyway, my 2 cents.  Thanks!

-- 
Marc (@wavded)
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Making super work outside a literal?

2011-06-23 Thread Brendan Eich
On Jun 23, 2011, at 12:07 PM, Axel Rauschmayer wrote:

 I believe you about the dynamic super. I can summarize my question as 
 follows:
 - Making super or current object available to a function incurs costs.
 
 These are two separate costs. You didn't define which 'super' but from 
 context I'll assume static. That's a function-creation-time internal 
 property setting cost.
 
 If by current object you mean |here|, please use that term for clarity's 
 sake. That has a per-call cost: an extra implicit parameter. We've been over 
 this about five times.
 
 Yes, I’m not questioning, just repeating and agreeing. And comparing the cost 
 of |here| to the cost |thisFunction|.

Oh, you meant the callee (the called function)? The current object phrase 
threw me.


 - Making current function available to a function does not incur costs? 
 This is *not* an extra parameter, then?
 
 Do you mean current object, aka |here|?
 
 If so, that's an extra parameter.
 
 If not, I don't know what you mean.
 
 Static super can only be accessed if you have a reference |thisFunction| to 
 the function that is currently executed. I would think that  |thisFunction| 
 would also incur costs, but Allen has since said that these costs are 
 negligible.

The called function is part of the evaluation results needed to call the 
function. It is indeed passed on the stack in naive stack-based 
implementations, to support reflection (e.g. arguments usage by the callee; 
again remember the caller in general does not know whether the callee uses 
arguments, debugger, etc.), and debugging (kind of hyper-reflection).

In a JIT, the calling convention can use registers and avoid writing to memory 
more than the minimum needed based on whatever analysis the JIT can support.

In any event, there's no extra parameter beyond the situation in today's 
engines. With dynamic 'super', there is.


 Related topic: How would |super| be handled if |this| is lexical?

There's no connection, AFAIK. But we also don't have a lexical-this proposal in 
Harmony yet.

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


Re: block-lambda revival

2011-06-23 Thread Jorge
On 23/06/2011, at 23:01, Marc Harter wrote:

 Peter Michaux encouraged me to write my thoughts on es-discuss so here I am.
 
 Out of the various new function syntaxes proposed ( -, #, {||} ) I
 have really taken a liking to the block-lambda revival strawman.  I
 think in general they all address similar wishes (e.g. implicit
 return, this, shorter). I prefer the block-lambda because of some use
 cases:
 
 let a = [1,2,3,4];
 let b = a.reduce((a,b) - a + b) // didn't see an example for this one
 assuming this is how it looks
 let b = a.reduce {|a,b| a + b} // less cluttery, fn bound by braces,
 couple characters less to type
 
 Self executing function expressions
 
 (- {
  // multi-line
 }())
 
 {||
  // multi-line -- i'm assuming there wouldn't need to be parens
 around the whole thing because block lambdas are expressions not
 statements (is this the case with arrow?)
 }()
 
 I like block-lambda because:
 
  1. From my understanding braces aren't going away, lets just embrace
 them (use them as part of the syntax)
  2. Arrow gets too bulky with braces (although worked good for CoffeeScript)
  3. Seems to be terse yet clear
  4. Encloses the function
 
 It may be nice to have side by side comparisons of the different
 proposals doing the same operation.

Here: http://jorgechamorro.com/blocks.html

 Anyway, my 2 cents.  Thanks!

{|| ... } for shorter *function* syntax is my favorite too. +1(e9)

Also, if any { block } could be a lambda, perhaps we won't need that (nor any 
new) syntax for block-lambdas.

Also, I'd prefer to know/see clearly when a function is being call()ed, so I'm 
not very fond of paren-free calls: foo(bar) is clearly an invocation, unlike 
foo bar, and readability is more important than saving a few keystrokes.

The C language is still (and -ISTM- will be for a long time) important, so 
-IMO- every little bit of JS's C-like syntax is a plus: less to learn: an old, 
popular, widely used, well-known, and familiar syntax.

JS -unlike other languages- is important enough that it does not need to follow 
these (dubious) trendy fashions to become popular. Nor to survive.

Proper punctuation aids comprehension and we're programming, not writing quick 
SMSs.
-- 
Jorge.___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Making super work outside a literal?

2011-06-23 Thread Brendan Eich
On Jun 23, 2011, at 2:00 PM, Sean Eagan wrote:

 Ok, sorry it took me so long, but I agree that the general idea of
 Object.defineMethod is the best solution.  I think it can be improved
 upon though, by adding the following:
 
 Ability to use any property descriptor attributes when defining methods.
 Ability to assign accessor getters and setters as well which use the
 assigned to object as |super|.
 Avoid having to add a defineMethod proxy trap.

Great point! That would be something to avoid.


 Here are the two potential solutions I have in mind for this:
 
 * Have Object.defineProperty create new functions with updated
 [[Super]] when the value, get, or set attributes are functions
 that use super.

This seems enough, you're right.


 * Add an Object.defineSuperProperty which is the same as the existing
 Object.defineProperty except that it creates new functions with
 updated [[Super]] when the value, get, or set attributes are
 functions that use super.  It could potentially throw if no super
 functions are passed.  This one may still require a
 defineSuperProperty proxy trap, not sure.

I'm not sure we need this one. Does it really avoid the proxy trap addition?


 Also, I wonder if there is a need for a Function.prototype.isSuper
 similar to Function.prototype.isGenerator?

A generator is a kind of function. 'super' evaluates to an object. So this 
seems misplaced, but first, what use-case does it serve? Can you show an 
example that motivates it?

/be

 
 On Thu, Jun 23, 2011 at 10:51 AM, Allen Wirfs-Brock
 al...@wirfs-brock.com wrote:
 
 On Jun 23, 2011, at 3:14 PM, Sean Eagan wrote:
 
 On Thu, Jun 23, 2011 at 4:56 AM, Allen Wirfs-Brock
 al...@wirfs-brock.com wrote:
 If you don't have actual implementation experience with dynamic languages I
 think you guys will just have to take Brendan's and my word for this.
 
 I now understand and fully agree with your performance arguments
 against dynamic super.  However, I still believe that the dynamic
 super semantics are largely superior to the static super semantics.
 
 Fortunately, I think the dynamic super semantics can be simulated via
 static super, thus yielding the best of both approaches!
 
 Here's what I propose:
 
 Terminology:
 
 super function - a function that uses |super|
 super delegate function - A function which delegates to a super
 function stored in its [[SuperFunction]] internal property, passing a
 |super| binding stored in its [[Super]] internal property.
 
 so every super function still requires an implicit super parameter
 
 
 Semantics:
 
 When a super function is assigned as a method or accessor getter or
 setter either via an object literal, Object.defineProperty or direct
 assignment,
 this would add overhead to every [[Put]].  a test to see if the value is a 
 super function.  The way to avoid the test would be defer the test until the 
 value of the property was retrieved  (first time only perhaps. This is 
 essentially the same as  the dynamic super implementation strategy of 
 conditionally only passing the current object to a super function.  So, you 
 have traded overhead on ever call for over head on every [[Put]].  [[Put]]'s 
 probaby occur less often than [[Call]]'s but may still be too much.
 
 a super delegate function is created and assigned instead
 whose [[SuperFunction]] internal property is the super function being
 assigned, and whose [[Super]] internal property is the [[Prototype]]
 internal property of the object being assigned to.
 
 When a super delegate function is subsequently accessed from an
 object, e.g. o.methodThatUsesSuper or
 Object.getOwnPropertyDescriptor(o,
 accessorWithGetterOrSetterThatUsesSuper), this resolves to the
 [[TargetFunction]] internal property of the super delegate function.
 
 I believe you are saying that upon property revival, a super delegate 
 function reference is replaced with the value of its [[SuperFunction]].  
 This means there is an additional check (is the property value a super 
 delegate function) on every [[Get]].
 
 
 When a super function is called directly, e.g. superFunction() or
 superFunction.call(this), |super| is resolved as the [[Prototype]]
 internal property of the |this| of the call.
 
 How does it know it is being called directly?
 
 This seems to be the primary thing this approach adds to simple static 
 super.  Why is this really important?  Is there a common usage case that 
 requires this.  I don't believe it has been addressed by other OO languages.
 
 When a super delegate function is called, e.g.
 o.methodThatUsesSuper(), o.accessorWithGetterThatUsesSuper, or
 o.accessorWithSetterThatUsesSuper = foo, |super| is bound to the
 super delegate function's [[Super]] internal property.
 
 in other words, the super delegate function calls the super function passing 
 the value of its [[Super]] as the implicit super parameter
 
 
 
 The equivalence class of a super function in  == and === consists of
 the super function and all of its corresponding 

Re: block-lambda revival

2011-06-23 Thread Brendan Eich
On Jun 23, 2011, at 3:14 PM, Jorge wrote:

 Anyway, my 2 cents.  Thanks!
 
 {|| ... } for shorter *function* syntax is my favorite too. +1(e9)

Thanks -- I am continuing to maintain arrow function syntax and block lambda 
revival as strawmen.

Arrows now require only two-token lookahead, ignoring the #!~ prefixes proposed 
for non-configurable, non-writable, and non-enumerable property assignments in 
object initialisers. This is in order to support either an object literal body 
or a braced non-empty block body where the block's first statement is not a 
labeled statement.

Block lambda revival has more grammar changes, but so far they check out.


 Also, if any { block } could be a lambda, perhaps we won't need that (nor any 
 new) syntax for block-lambdas.

We would need new syntax still, for formal parameters.

Making blocks be expressions requires unifying the ObjectLiteral and Block 
productions. I don't know how to do this in without at least two-token 
lookeahead, and it is not a backward compatible change if done for all places 
where Statement : Block in the current grammar.


 Also, I'd prefer to know/see clearly when a function is being call()ed, so 
 I'm not very fond of paren-free calls: foo(bar) is clearly an invocation, 
 unlike foo bar,

Your example is too abstracted to be fair. Concretely, the latter will *always* 
look like foo {|| bar} ... and never foo bar for any bar.


 and readability is more important than saving a few keystrokes.

Readability arguments support the paren-free syntax too. You can't win this by 
selective arguing.


 The C language is still (and -ISTM- will be for a long time) important, so 
 -IMO- every little bit of JS's C-like syntax is a plus: less to learn: an 
 old, popular, widely used, well-known, and familiar syntax.

C by way of Java, and both are boat anchors. Again, where pray tell is 
'function' in C?


 JS -unlike other languages- is important enough that it does not need to 
 follow these (dubious) trendy fashions to become popular. Nor to survive.

Nothing trendy about Smalltalk blocks unless you are a Rubyist.


 Proper punctuation aids comprehension and we're programming, not writing 
 quick SMSs.

This is silly, you're making vague arguments that cut both ways.

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


Re: block-lambda revival

2011-06-23 Thread Rob Campbell
I'm liking the block-lambda syntax, I think more than the arrow. One possible 
shortening could be to exclude the second bar (|) if no argument variables are 
specified.

{| // some block of code };

I don't *think* we'd ever start an expression with a single | operator, so 
there should be no ambiguity.

On 2011-06-23, at 19:27, Brendan Eich wrote:

 On Jun 23, 2011, at 3:14 PM, Jorge wrote:
 
 Anyway, my 2 cents.  Thanks!
 
 {|| ... } for shorter *function* syntax is my favorite too. +1(e9)
 
 Thanks -- I am continuing to maintain arrow function syntax and block lambda 
 revival as strawmen.
 
 Arrows now require only two-token lookahead, ignoring the #!~ prefixes 
 proposed for non-configurable, non-writable, and non-enumerable property 
 assignments in object initialisers. This is in order to support either an 
 object literal body or a braced non-empty block body where the block's first 
 statement is not a labeled statement.
 
 Block lambda revival has more grammar changes, but so far they check out.
 
 
 Also, if any { block } could be a lambda, perhaps we won't need that (nor 
 any new) syntax for block-lambdas.
 
 We would need new syntax still, for formal parameters.
 
 Making blocks be expressions requires unifying the ObjectLiteral and Block 
 productions. I don't know how to do this in without at least two-token 
 lookeahead, and it is not a backward compatible change if done for all places 
 where Statement : Block in the current grammar.
 
 
 Also, I'd prefer to know/see clearly when a function is being call()ed, so 
 I'm not very fond of paren-free calls: foo(bar) is clearly an invocation, 
 unlike foo bar,
 
 Your example is too abstracted to be fair. Concretely, the latter will 
 *always* look like foo {|| bar} ... and never foo bar for any bar.
 
 
 and readability is more important than saving a few keystrokes.
 
 Readability arguments support the paren-free syntax too. You can't win this 
 by selective arguing.
 
 
 The C language is still (and -ISTM- will be for a long time) important, so 
 -IMO- every little bit of JS's C-like syntax is a plus: less to learn: an 
 old, popular, widely used, well-known, and familiar syntax.
 
 C by way of Java, and both are boat anchors. Again, where pray tell is 
 'function' in C?
 
 
 JS -unlike other languages- is important enough that it does not need to 
 follow these (dubious) trendy fashions to become popular. Nor to survive.
 
 Nothing trendy about Smalltalk blocks unless you are a Rubyist.
 
 
 Proper punctuation aids comprehension and we're programming, not writing 
 quick SMSs.
 
 This is silly, you're making vague arguments that cut both ways.
 
 /be
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

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


Re: block-lambda revival

2011-06-23 Thread Mark S. Miller
[+stay]

Another bit of evidence for lexical this, and thus for block lambdas over
arrow functions or simple # functions.

At 
http://wiki.ecmascript.org/doku.php?id=harmony:proxiesrev=1308499413do=diff
I corrected a bug noticed just now by Mike Stay (cc'ed). The bug dates from

http://wiki.ecmascript.org/doku.php?id=harmony:proxiesrev=1280925681#trap_defaults
in August of 2010, more than 10 months ago, when Tom van Cutsem wrote:

keys: function() {
  return this.getOwnPropertyNames().filter(
function (name) { return
this.getOwnPropertyDescriptor(name).enumerable });
}

This bug was written by one of the most talented and careful programmers I
have ever met. The page it appears in has been carefully examined by many
experts (not just official experts -- real experts) and a large community of
talented people, guiding at least three implementations of the proxy system.
The bug was only noticed by Mike Stay while starting the newest of these
implementation efforts, emulating proxies on old browsers within ES5/3.

Most JavaScript code will be much less reviewed than this, and by a
community less expert than ourselves in the peculiarities of the language.
We need to ask, why was this bug so easy for an expert to make and so hard
for a community of experts to catch? My guess is that it's because
Array.prototype.filter feels like a control structure and the anon
function we're calling it with feels like a control structure block, even
though we know that we know otherwise. When we see the this inside and try
to figure out what it means, we search outward for a function and our eye
often catches the wrong one.


Let's see what Tom might have written with three of the other function-like
proposals. To be fair, I'll assume here that return can be omitted in all.

Arrow functions:

keys: function() {
  return this.getOwnPropertyNames().filter(
(name) - this.getOwnPropertyDescriptor(name).enumerable );
}

Simple # functions

keys: function() {
  return this.getOwnPropertyNames().filter(
#(name) { this.getOwnPropertyDescriptor(name).enumerable });
}

block lambdas

keys: function() {
  return this.getOwnPropertyNames().filter { |name|
this.getOwnPropertyDescriptor(name).enumerable
  }
}

The first and obvious point I'm making is that Tom would not have made this
particular mistake with block lambdas, but I recognize that this argument
cuts both ways. Other uses may have the opposite hazard, and we need to
examine this as well. The new point is that arrow functions and simple #
functions make the original hazard *worse*, because, like function, they
still rebind this. But by being less verbose than function, it's even
easier for the eye to miss them when seeing a this in their body and
trying to determine what it means.

The more I think about this, the more I'm inclined to believe that, for
functions which rebind this, the verbosity of function is a virtue. As
fallible programmers, we can only afford a more compact function notation
for defining functions with lexical this -- like block lambdas.

-- 
  Cheers,
  --MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: block-lambda revival

2011-06-23 Thread Brendan Eich
On Jun 23, 2011, at 5:16 PM, Mark S. Miller wrote:

 Arrow functions:
 
 keys: function() {
   return this.getOwnPropertyNames().filter(
 (name) - this.getOwnPropertyDescriptor(name).enumerable );
 }

This is not giving arrow functions their due, though. Just use = and all is 
well.

Yes, you have to remember, but as you note, the which this? cuts both ways.


 Simple # functions
 
 keys: function() {
   return this.getOwnPropertyNames().filter(
 #(name) { this.getOwnPropertyDescriptor(name).enumerable });
 }

Aside: we don't have a live proposal to use # this way, with completion value 
as implicit return value. Full 'return' or something like the empty-label hack 
I sketched (prefix : followed by tail position) would be needed. Also, # for 
frozen value counterparts (records and tuples, as well as functions) seems a 
better use of that character.


 block lambdas
 
 keys: function() {
   return this.getOwnPropertyNames().filter { |name|
 this.getOwnPropertyDescriptor(name).enumerable
   }
 }
 
 The first and obvious point I'm making is that Tom would not have made this 
 particular mistake with block lambdas, but I recognize that this argument 
 cuts both ways. Other uses may have the opposite hazard, and we need to 
 examine this as well. The new point is that arrow functions and simple # 
 functions make the original hazard *worse*, because, like function, they 
 still rebind this.

While - does bind |this| dynamically, = does not.


 But by being less verbose than function, it's even easier for the eye to 
 miss them when seeing a this in their body and trying to determine what it 
 means.

You're right that it's easy to miss the bad thing, even if there's a good thing.


 The more I think about this, the more I'm inclined to believe that, for 
 functions which rebind this, the verbosity of function is a virtue.

But it didn't help in the story you led with :-).


 As fallible programmers, we can only afford a more compact function notation 
 for defining functions with lexical this -- like block lambdas.

Or =?

I'm leaning toward block lambdas myself, but I feel the need to play umpire 
here a bit -- arrows need fair play including =, not just -.

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


Re: block-lambda revival

2011-06-23 Thread Brendan Eich
On Jun 23, 2011, at 7:04 PM, Mike Samuel wrote:

 2011/6/23 Brendan Eich bren...@mozilla.com:
 On Jun 23, 2011, at 4:07 PM, Rob Campbell wrote:
 
 I'm liking the block-lambda syntax, I think more than the arrow. One
 possible shortening could be to exclude the second bar (|) if no argument
 variables are specified.
 {| // some block of code };
 
 This does not work. How do you know that what follows the first | is not a
 formal parameter?
 Formal parameter syntax looks like expression syntax -- currently Expression
 covers FormalParameterList. Arrow function syntax relies on this.
 /be
 
 Are you thinking that
 
   {| a | a }
 
 it is ambiguous whether
 
function (a) { return a; }
 
 or
 
function () { return a | a; }


Precisely.

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


Re: Making super work outside a literal?

2011-06-23 Thread Brendan Eich
On Jun 23, 2011, at 10:39 PM, Axel Rauschmayer wrote:

 Related topic: How would |super| be handled if |this| is lexical?
 
 There's no connection, AFAIK. But we also don't have a lexical-this proposal 
 in Harmony yet.
 
 I would expect problems that are similar to that = this:
 
 var obj = {
mymethod: function(arr) {
arr.forEach(function(x) {
super.mymethod(x); // would this work?
});
}
 }

From http://wiki.ecmascript.org/doku.php?id=harmony:object_initialiser_super :

PrimaryExpression : ...
super 
The value of super is the same as the value of this but when super is used as 
the base of a property access the property lookup starts with the object that 
is the prototype of the object defined by the object literal that contains the 
reference to super.

This seems to say that the wrong |this| would be used, with the right property 
lookup starting point. Yikes.


 Thankfully, I don’t think that super-calls will be very common in typical 
 JavaScript code, in contrast to this.

Not sure this will all pan out as proposed. 'super' in classes works. 'super' 
in any function nested however deeply in an object initialiser, perhaps not. If 
the above spec constrained the nesting to be immedate method of, that would 
seem to solve it. But would that be too restrictive?

/be


 
 -- 
 Dr. Axel Rauschmayer
 
 a...@rauschma.de
 twitter.com/rauschma
 
 home: rauschma.de
 blog: 2ality.com
 
 
 

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