Re: [[Extensible]]and Proxies (Was: Proxy.isProxy )

2011-07-18 Thread David Bruant

Le 18/07/2011 02:58, Brendan Eich a écrit :

On Jul 17, 2011, at 3:14 PM, David Bruant wrote:
I'm only catching up now on this thread. I have indeed started some 
work to try to implement an invariant-enforcing implementation of 
preventExtension rather than fix+become.


Just off the top of my head, sorry if I'm misunderstanding: fix based 
on become is very attractive to VM implementors, because it avoids 
extra for-life-of-fixed-object costs in the proxy or native code paths 
that aren't already there with Proxies as proposed and with ES5.


"becomes" lets the brain-swapped objects do what they do best. There's 
no hybridization as if by composition using vtbls, if statements, or 
whatever, that affects proxy codepaths. It's true one could "become" a 
proxy with the extra code paths, but that's duplicative at some level 
(not necessarily code inlining, but layering the extra 
preventExtensions enforcement somehow).


If the preventExtensions enforcement is the same as the pre-fix 
overhead for fixed properties, perhaps this is less of an issue.
I was in doubt for some time and I realized that the fixed properties 
required very few checks and these checks turn out to be the same 
performed by some code defined in a way or another in one of the ES5.1 
8.12 algorithms.
By enforcing ES5 invariants, we actually are trying to enforce things 
that are enforced for normal objects already. If you haven't read Tom's 
FixedHandler implementation [1], I encourage you to, because the 
minimalism of it is quite interesting.
Especially, in the get{Own}PropertyDescriptor and defineProperty traps, 
Object.defineProperty is called and as commented, the purpose is to 
(re)use the argument-checking code of this method to let it throw if 
needed. It's extremely generic and future-proof with regard to new sorts 
of property descriptors.
We'll see what the implementation of invariant checking non-extensible 
proxies looks like.



Sticking with becomes, but (a) distinguishing preventExtensions from 
seal from freeze and (b) allowing the [[Class]] or ES.next equivalent 
to be controlled would allow, e.g., Proxy-emulated Arrays that fix to 
become real (pE'ed, sealed, or frozen) Arrays.
Distinguishing preventExtensions from seal from freeze will still be 
possible with an invariant-enforcing proxy if that's the chosen solution.


David

[1] 
http://code.google.com/p/es-lab/source/browse/trunk/src/proxies/FixedHandler.js

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


Re: [[Extensible]]and Proxies (Was: Proxy.isProxy )

2011-07-18 Thread David Bruant

Le 18/07/2011 03:03, Brendan Eich a écrit :

On Jul 17, 2011, at 6:01 PM, Brendan Eich wrote:


See my previous reply, about fixed properties, the fix trap, controlling the [[Class]] of 
the object the proxy "becomes" upon fixing, and preserving the 
(preventExtensions, seal, freeze) distinction when fixing.

Here's a possibly dumb question: why not have fix return not a pdmap for the 
new Object instance to be fixed at those properties, rather an object (of any 
class) to be fixed by the exact cause of the fix trap: preventExtensions, seal, 
or freeze?

Interesting. What would happen if the returned object is a proxy?

Regardless, my understanding of the fix+become design was to enforce the 
non-extensibility invariants (and if I'm missing something, please tell 
me so). I have to admit that it really feels weird to me that because I 
call Object.{preventExtensions|seal|freeze}, my handler should stop its 
existence and my proxy should "become" another object (even a native 
array or a DOM Node if we want to allow that). It sounds very arbitrary 
to me. Why does preventing extension should throw my loggers away? Or 
stop the forwarding of all operations to the target object if I defined 
a forwarder?
Actually, I've raised the issue in another thread that a forwarder proxy 
cannot properly forward Object.{preventExtensions|seal|freeze} to the 
target object because within the fix trap, there is no way to 
distinguish between the 3.


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


An "extend" operator is a natural companion to <|

2011-07-18 Thread Allen Wirfs-Brock
I've recently been experimenting with coding both prototypal and class based 
object definitions using the various syntactic forms that are currently on the 
table.  Something has emerged from that which has surprised me.  I have never 
been a big fan of the "extend" method that is provided by a number of 
JavaScript frameworks. However, based upon my experiments I'm now think that 
something like extend solves several issues with the declarative object and 
class declarations that we have recently been discussing.

Just in case there is anyone on this list who isn't familiar with extend, here 
is a quick explanation. In most frameworks that support it, "extend" is invoked 
something like this: 
   obj.extend(extensionObj)
It copies the own properties of  extensionObj and makes corresponding own 
properties for obj.  Exact details about which properties are copied, various 
error conditions and even the name of the method varies among frameworks.  It 
is generally has been used as an imperative supplement to ECMASript's built-in 
prototype inheritance, for example to provide effects similar to multiple 
inheritance. 

The use cases that interests me are some what different then this current 
common use. 

But first, I'll cut to the chase. Here is a quick summary of what I'm going to 
propose:

In addition to  <| we need another operator <& that is similar to the "extend" 
method in various frameworks.  It replicates the own properties of its RHS 
operation on its LHS operand.  It provides an easy declarative way to describe 
the properties that need to be added to an already created object. For example:

obj <& {
   __constDataProp: x,
   method(a) {return a+this._constDataProp},
   get konst() {return this.__costDataProp}
};

adds three properties to obj. 
   
So, on to the use cases that motivates this. In 
https://mail.mozilla.org/pipermail/es-discuss/2011-July/015792.html  I used an 
prototypal inheritance pattern in an example.  A slightly simplified version of 
the example is:

const Point = {
 //private members
 __x: 0,
 __y: 0, 
 __validate(x,y) { return typeof x == 'number' && typeof y = 'number'},
 //public members
 new(x,y) {
  if (!this.__validate(x,y)) throw "invalid";
  return this <| {
  __x: x,
  __y: y
 }
  };
}

In this pattern, the "new" method on a prototype object is used to create 
instance of the corresponding object abstraction.  It does this by using the <| 
operator to create the instance as an object whose [[Protoype]] is set to the 
prototypal instance.  The object literal on the right of the <| lists the per 
instance state of the new object.  In this case the properties named "__x" and 
"__y".   This is a nice declarative way to describe the per instance state but 
it turns out it doesn't generalize very well to multiple levels of inheritance. 
 If you tried to use this pattern to create a three dimensional point,  it 
would probably look something like:

const Point3D = Point <| {
 //private members
 __z: 0,
 //public members
 new(x,y,z) {
  if (!this.__validate(x,y) || typeof z != 'number') throw "invalid";
  return this <| {
  __x: x,
  __y: y,
 __z: z
 }
  };
}

Note that the "new" method in Point3D had to essentially copy everything that 
was in the "new" method of Point.  This isn't very good use of inheritance. It 
also may not work if true private properties are used instead of just a naming 
convention. What you would really like to do is to let the implementation of 
"new" in Point do all the work that relates to x and y and only have to include 
in Point3D code that relates to z. You might be tempted to write it as:

const Point3D = Point <| {
 //private members
 __z: 0,
 //public members
 new(x,y,z) {
  if (typeof z != 'number') throw "invalid";
  return super.new(x,y) <| {
 __z: z
 }
  };
}

However, that wouldn't create what was probably intended. Instead of creating a 
single instance object that inherits from Point3D it creates two objects, the 
first one has Point3D as its [[Prototype]] and has own properties "__x" and 
"__y".  The second object has the first object as its [[Prototype]] and as 
"__z" as an own property.  If a Point4D was created following the same pattern 
the per instance state of create by each call of Point4D would be spread over 
three objects.  The problem is that we want to do a super.new call at each 
level of the inheritance hierarchy to ensure that we do all the necessary 
initialization without unnecessary code copying.  However, each level is doing 
a <| which creates a distinct object.  Instead, what we really want to do is 
create a single object at the top of the inheritance hierarchy and then add 
additional properties to that object at each inheritance level. If we want to

Re: [[Extensible]]and Proxies (Was: Proxy.isProxy )

2011-07-18 Thread Brendan Eich
On Jul 18, 2011, at 2:35 AM, David Bruant wrote:

> Le 18/07/2011 03:03, Brendan Eich a écrit :
>> On Jul 17, 2011, at 6:01 PM, Brendan Eich wrote:
>> 
>>> See my previous reply, about fixed properties, the fix trap, controlling 
>>> the [[Class]] of the object the proxy "becomes" upon fixing, and preserving 
>>> the (preventExtensions, seal, freeze) distinction when fixing.
>> Here's a possibly dumb question: why not have fix return not a pdmap for the 
>> new Object instance to be fixed at those properties, rather an object (of 
>> any class) to be fixed by the exact cause of the fix trap: 
>> preventExtensions, seal, or freeze?
> Interesting. What would happen if the returned object is a proxy?

Good question. First impulse is to make that an error, but if proxies can be 
fixed, then the possibility of a fixed and inextensible proxy sufficing as 
return value of this hypothetical fix trap is plausible.

We would need continued, VM-level enforcement that such a fixed proxy cannot be 
extended, and of course that all of its properties are fixed.


> Regardless, my understanding of the fix+become design was to enforce the 
> non-extensibility invariants (and if I'm missing something, please tell me 
> so). I have to admit that it really feels weird to me that because I call 
> Object.{preventExtensions|seal|freeze}, my handler should stop its existence 
> and my proxy should "become" another object (even a native array or a DOM 
> Node if we want to allow that). It sounds very arbitrary to me.

The original proxy design had no support for fixed properties, so no way to let 
the handler intercede after fix without leaving too much bug/attack surface.

If we extend proxies to support fixed properties and ![[Extensible]], then we 
may be able to relax the design. But nothing here is truly arbitrary. It's a 
divide-and-conquer progression, I think.

Also, to repeat: implementation of becomes with a newborn is really quite slick 
and relatively easy to support, compared to more invasive fixed/inextensible 
enforcement.


> Why does preventing extension should throw my loggers away? Or stop the 
> forwarding of all operations to the target object if I defined a forwarder?

Because there was no way in sight to enforce the critical invariants. Possibly 
there is, now.


> Actually, I've raised the issue in another thread that a forwarder proxy 
> cannot properly forward Object.{preventExtensions|seal|freeze} to the target 
> object because within the fix trap, there is no way to distinguish between 
> the 3.

Yes indeed.

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


Re: Array.prototype.concat result length (ES5.1)

2011-07-18 Thread Jeff Walden

On 07/14/2011 10:04 AM, Allen Wirfs-Brock wrote:

It is probably a bug, because array index based operations generally warp 
around to 0 at 2^32.


Freudian slip?  :-D

Easiest fix is to just add the length-set to concat.  For a quick ES5 erratum 
that seems best to me.

Removing all the RangeError stuff, and making array indexes just non-negative 
integers,  would be nice for ES6 or similar.  I suspect changing that won't 
break anyone worth caring about, although I do know some people have taken the 
time to care about this in the past (mostly in a spec-nut way :-) ):

http://hexmen.com/blog/2006/12/push-and-pop/

Without having thought too hard about exactly what would be involved, I suspect the 
amount of stuff you'd need to adjust, and the complexity of checking for sane behavior in 
all cases (including some of the 2**52 upper-bounding edge cases, depending on what new 
semantics you might want for "array indexes" or whatever), would make it unwise 
to try for ES5 errata.  But I could well be wrong about this, so I wouldn't necessarily 
write off that possibility.

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


Re: [[Extensible]]and Proxies (Was: Proxy.isProxy )

2011-07-18 Thread Brendan Eich
On Jul 18, 2011, at 2:06 AM, David Bruant wrote:

> By enforcing ES5 invariants, we actually are trying to enforce things that 
> are enforced for normal objects already. If you haven't read Tom's 
> FixedHandler implementation [1], I encourage you to, because the minimalism 
> of it is quite interesting.

Read it, very slick. Has it changed recently?


> Especially, in the get{Own}PropertyDescriptor and defineProperty traps, 
> Object.defineProperty is called and as commented, the purpose is to (re)use 
> the argument-checking code of this method to let it throw if needed. It's 
> extremely generic and future-proof with regard to new sorts of property 
> descriptors.

That is a good sign, and anything else would be a "bad sign" ;-).


> We'll see what the implementation of invariant checking non-extensible 
> proxies looks like.

This is the crucial part.


>> Sticking with becomes, but (a) distinguishing preventExtensions from seal 
>> from freeze and (b) allowing the [[Class]] or ES.next equivalent to be 
>> controlled would allow, e.g., Proxy-emulated Arrays that fix to become real 
>> (pE'ed, sealed, or frozen) Arrays.
> Distinguishing preventExtensions from seal from freeze will still be possible 
> with an invariant-enforcing proxy if that's the chosen solution.

Is there a proposal?

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


Re: Array.prototype.concat result length (ES5.1)

2011-07-18 Thread Allen Wirfs-Brock

On Jul 18, 2011, at 10:51 AM, Jeff Walden wrote:

> 
> Easiest fix is to just add the length-set to concat.  For a quick ES5 erratum 
> that seems best to me.

Yes, this needs to be in the errata.

> 
> Removing all the RangeError stuff, and making array indexes just non-negative 
> integers,  would be nice for ES6 or similar.  I suspect changing that won't 
> break anyone worth caring about, although I do know some people have taken 
> the time to care about this in the past (mostly in a spec-nut way :-) ):
> 
> http://hexmen.com/blog/2006/12/push-and-pop/
> 
> Without having thought too hard about exactly what would be involved, I 
> suspect the amount of stuff you'd need to adjust, and the complexity of 
> checking for sane behavior in all cases (including some of the 2**52 
> upper-bounding edge cases, depending on what new semantics you might want for 
> "array indexes" or whatever), would make it unwise to try for ES5 errata.  
> But I could well be wrong about this, so I wouldn't necessarily write off 
> that possibility.

We won't do this as an errata.  It is a change that would have to be treated as 
a change in a future edition rather than an error correction of the current 
edition.


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


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Sean Eagan
It would also allow declarative non-integer own properties for arrays,
and arbitrary own properties to regular expressions, numbers,
booleans, and strings, though I can't think of any specific use cases
for those off of the top of my head.

Also, how about |> as opposed to <&, since it is a dual to <| adding
own rather than inherited properties?

On Mon, Jul 18, 2011 at 12:32 PM, Allen Wirfs-Brock
 wrote:
> I've recently been experimenting with coding both prototypal and class based
> object definitions using the various syntactic forms that are currently on
> the table.  Something has emerged from that which has surprised me.  I have
> never been a big fan of the "extend" method that is provided by a number of
> JavaScript frameworks. However, based upon my experiments I'm now think that
> something like extend solves several issues with the declarative object and
> class declarations that we have recently been discussing.
> Just in case there is anyone on this list who isn't familiar with extend,
> here is a quick explanation. In most frameworks that support it, "extend" is
> invoked something like this:
>    obj.extend(extensionObj)
> It copies the own properties of  extensionObj and makes corresponding own
> properties for obj.  Exact details about which properties are copied,
> various error conditions and even the name of the method varies among
> frameworks.  It is generally has been used as an imperative supplement to
> ECMASript's built-in prototype inheritance, for example to provide effects
> similar to multiple inheritance.
> The use cases that interests me are some what different then this current
> common use.
> But first, I'll cut to the chase. Here is a quick summary of what I'm going
> to propose:
> In addition to  <| we need another operator <& that is similar to the
> "extend" method in various frameworks.  It replicates the own properties of
> its RHS operation on its LHS operand.  It provides an easy declarative way
> to describe the properties that need to be added to an already created
> object. For example:
>
> obj <& {
>    __constDataProp: x,
>    method(a) {return a+this._constDataProp},
>    get konst() {return this.__costDataProp}
> };
>
> adds three properties to obj.
>
> So, on to the use cases that motivates this. In
> https://mail.mozilla.org/pipermail/es-discuss/2011-July/015792.html  I used
> an prototypal inheritance pattern in an example.  A slightly simplified
> version of the example is:
>
> const Point = {
>      //private members
>      __x: 0,
>      __y: 0,
>      __validate(x,y) { return typeof x == 'number' && typeof y = 'number'},
>      //public members
>      new(x,y) {
>           if (!this.__validate(x,y)) throw "invalid";
>           return this <| {
>                   __x: x,
>                   __y: y
>                  }
>       };
> }
>
> In this pattern, the "new" method on a prototype object is used to create
> instance of the corresponding object abstraction.  It does this by using the
> <| operator to create the instance as an object whose [[Protoype]] is set to
> the prototypal instance.  The object literal on the right of the <| lists
> the per instance state of the new object.  In this case the properties named
> "__x" and "__y".   This is a nice declarative way to describe the per
> instance state but it turns out it doesn't generalize very well to multiple
> levels of inheritance.  If you tried to use this pattern to create a three
> dimensional point,  it would probably look something like:
>
> const Point3D = Point <| {
>      //private members
>      __z: 0,
>      //public members
>      new(x,y,z) {
>           if (!this.__validate(x,y) || typeof z != 'number') throw
> "invalid";
>           return this <| {
>                   __x: x,
>                   __y: y,
>                  __z: z
>                  }
>       };
> }
>
> Note that the "new" method in Point3D had to essentially copy everything
> that was in the "new" method of Point.  This isn't very good use of
> inheritance. It also may not work if true private properties are used
> instead of just a naming convention. What you would really like to do is to
> let the implementation of "new" in Point do all the work that relates to x
> and y and only have to include in Point3D code that relates to z. You might
> be tempted to write it as:
>
> const Point3D = Point <| {
>      //private members
>      __z: 0,
>      //public members
>      new(x,y,z) {
>           if (typeof z != 'number') throw "invalid";
>           return super.new(x,y) <| {
>                  __z: z
>                  }
>       };
> }
>
> However, that wouldn't create what was probably intended. Instead of
> creating a single instance object that inherits from Point3D it creates two
> objects, the first one has Point3D as its [[Prototype]] and has own
> properties "__x" and "__y".  The second object has the first object as its
> [[Prototype]] and as "__z" as an own property.  If a Point4D was created
> followin

Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Brendan Eich
Hawt.

A bit rough in that LHS <& RHS mutates LHS, whereas LHS <| RHS is pure and 
produces a new object (which could be optimized to mutate RHS, note well!). 
Both <| and <& are operators, to support chaining. Would it be better for <& to 
be pure as <| is, and make an assignment operator form, LHS <&= RHS, that 
expands to LHS = LHS <& RHS?

Anyway, if I have <& right, then:

class SkinnedMesh extends THREE.Mesh {
  constructor(geometry, materials) {
super(geometry, materials);
 
public identityMatrix = new THREE.Matrix4();
public bones = [];
public boneMatrices = [];
...
  }
 
  update(camera) {
...
super.update();
  }
}

from http://wiki.ecmascript.org/doku.php?id=harmony:classes would desugar to:

function SkinnedMesh(geometry, materials) {
  return super(geometry, materials) <& {
identityMatrix: new THREE.Matrix4(),
bones: [],
boneMatrices: [],
...
  };
}

SkinnedMesh.prototype = THREE.Mesh.prototype <| {
  update(camera) {
...
super.update();
  }
};

Class-side inheritance could be done via

let SkinnedMesh = THREE.Mesh <| (function (geom, mats) { ... } <& { 
classMethod() {...} });

This loses the hoisting of SkinnedMesh that the function declaration desugaring 
gained "for free" -- another rough spot to smooth out.

There's still a usability argument for class syntax, certainly.

Class syntax is also, for some folks, an attractive nuisance because of 
single-inheritance OOP being oversold and very often the wrong paradigm. But <& 
helps there too -- one can more conveniently make mixins (I must mean <&= here, 
of course).

The last conflicting name wins, or so it seems from what you've written. The 
compositional answer there is to seal properties you don't want anyone to 
redefine by a conflicting extend operation. I'm assuming the internal method 
used to update the LHS or populate the new copy of it is [[DefineOwnProperty]], 
as with ES5 object literals, and not [[Put]].

/be

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


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Allen Wirfs-Brock

On Jul 18, 2011, at 11:29 AM, Sean Eagan wrote:

> It would also allow declarative non-integer own properties for arrays,
> and arbitrary own properties to regular expressions, numbers,
> booleans, and strings, though I can't think of any specific use cases
> for those off of the top of my head.

Yes, I should have mentioned at least the array case.

> 
> Also, how about |> as opposed to <&, since it is a dual to <| adding
> own rather than inherited properties?

I'd be a bit concerned about  some people getting confused about which 
direction of the "arrow" corresponds to each operation.  Might be particularly 
hard for people with dyslexia.  I have played around with some other 
possibilities, for example, +<| .

I like the nemonic value of having + or & as part of the operator symbol for 
"extend" but  unfortunately <+ can't be used.

Allen






> 
> On Mon, Jul 18, 2011 at 12:32 PM, Allen Wirfs-Brock
>  wrote:
>> I've recently been experimenting with coding both prototypal and class based
>> object definitions using the various syntactic forms that are currently on
>> the table.  Something has emerged from that which has surprised me.  I have
>> never been a big fan of the "extend" method that is provided by a number of
>> JavaScript frameworks. However, based upon my experiments I'm now think that
>> something like extend solves several issues with the declarative object and
>> class declarations that we have recently been discussing.
>> Just in case there is anyone on this list who isn't familiar with extend,
>> here is a quick explanation. In most frameworks that support it, "extend" is
>> invoked something like this:
>>obj.extend(extensionObj)
>> It copies the own properties of  extensionObj and makes corresponding own
>> properties for obj.  Exact details about which properties are copied,
>> various error conditions and even the name of the method varies among
>> frameworks.  It is generally has been used as an imperative supplement to
>> ECMASript's built-in prototype inheritance, for example to provide effects
>> similar to multiple inheritance.
>> The use cases that interests me are some what different then this current
>> common use.
>> But first, I'll cut to the chase. Here is a quick summary of what I'm going
>> to propose:
>> In addition to  <| we need another operator <& that is similar to the
>> "extend" method in various frameworks.  It replicates the own properties of
>> its RHS operation on its LHS operand.  It provides an easy declarative way
>> to describe the properties that need to be added to an already created
>> object. For example:
>> 
>> obj <& {
>>__constDataProp: x,
>>method(a) {return a+this._constDataProp},
>>get konst() {return this.__costDataProp}
>> };
>> 
>> adds three properties to obj.
>> 
>> So, on to the use cases that motivates this. In
>> https://mail.mozilla.org/pipermail/es-discuss/2011-July/015792.html  I used
>> an prototypal inheritance pattern in an example.  A slightly simplified
>> version of the example is:
>> 
>> const Point = {
>>  //private members
>>  __x: 0,
>>  __y: 0,
>>  __validate(x,y) { return typeof x == 'number' && typeof y = 'number'},
>>  //public members
>>  new(x,y) {
>>   if (!this.__validate(x,y)) throw "invalid";
>>   return this <| {
>>   __x: x,
>>   __y: y
>>  }
>>   };
>> }
>> 
>> In this pattern, the "new" method on a prototype object is used to create
>> instance of the corresponding object abstraction.  It does this by using the
>> <| operator to create the instance as an object whose [[Protoype]] is set to
>> the prototypal instance.  The object literal on the right of the <| lists
>> the per instance state of the new object.  In this case the properties named
>> "__x" and "__y".   This is a nice declarative way to describe the per
>> instance state but it turns out it doesn't generalize very well to multiple
>> levels of inheritance.  If you tried to use this pattern to create a three
>> dimensional point,  it would probably look something like:
>> 
>> const Point3D = Point <| {
>>  //private members
>>  __z: 0,
>>  //public members
>>  new(x,y,z) {
>>   if (!this.__validate(x,y) || typeof z != 'number') throw
>> "invalid";
>>   return this <| {
>>   __x: x,
>>   __y: y,
>>  __z: z
>>  }
>>   };
>> }
>> 
>> Note that the "new" method in Point3D had to essentially copy everything
>> that was in the "new" method of Point.  This isn't very good use of
>> inheritance. It also may not work if true private properties are used
>> instead of just a naming convention. What you would really like to do is to
>> let the implementation of "new" in Point do all the work that relates to x
>> and y and only have to include in Point3D code that relates to z. You might
>> be tempted to write it as:
>> 
>> const Point3D = Point <| {
>>   

Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread David Bruant
Le 18/07/2011 19:32, Allen Wirfs-Brock a écrit :
> I've recently been experimenting with coding both prototypal and class
> based object definitions using the various syntactic forms that are
> currently on the table.  Something has emerged from that which has
> surprised me.  I have never been a big fan of the "extend" method that
> is provided by a number of JavaScript frameworks. However, based upon
> my experiments I'm now think that something like extend solves several
> issues with the declarative object and class declarations that we have
> recently been discussing.
>
> Just in case there is anyone on this list who isn't familiar with
> extend, here is a quick explanation. In most frameworks that support
> it, "extend" is invoked something like this: 
>obj.extend(extensionObj)
> It copies the own properties of  extensionObj and makes corresponding
> own properties for obj.
Very recently, I have read jQuery source code of jQuery.extend and I
have been surprised to discover that actually not only own properties
are copied. See definition at [1] and the main for-in loop between lines
334 and 360. Do anyone has an idea of why it is like this?


> (...)
>
> So, why use an operator like <& instead of a method named "extend":
> 1)  A big reason is that frameworks already use the extend name and
> the exact semantics we would define for it are only to match the
> current semantics of these frameworks.  By not using that name we
> avoid compatibility issues.
> 2) A operator form such as <& avoids issue of method redefinition and
> can more easily added to existing syntactic forms such as function
> declarations.
> 3) It is conceptually natural a natural companion to <|.  It makes
> sense to learn about the two operators together (particularly with
> regard to object literals on the RHS).
4) It makes static analysis easier. I'm currently working on some
JavaScript analysis, trying to extract out the API of a JS library.
Plenty of cases are easy. However, jQuery, defines its API in literal
objects which "extend" jQuery (see [2], for instance) or
jQuery.prototype (jQuery.fn). Doing a static analysis which will be able
to figure this one out will be extremely hard at the very best and most
likely impossible at all (because it will require my static analysis to
understand jQuery.extend semantics, which sounds impossible to me for now)
Having some syntax for that will make the analysis I want to do not only
possible, but easy.

Having a standardized "extend" method would make the static analysis
possible with the extra burden of making sure it has not been overridden
which is impossible in some cases (think obj[var1 + var2] = 1;).

On a related note, as I said, I'm working on extracting a "JavaScript
API" out of a JS file. For that very purpose, I cannot think of
something more useful than a class syntax.
Overall, I am highly in favor of language constructs that make
Javascript more suitable for reliable and easy machine understandability
as it will allow to extract more useful information just based on the
source code.

> I think <& is a natural companion to <| and is in line with our goals
> to both enhancing object literals and providing a class declarations
> as alternative to stand-alone constructor functions.  It increases the
> expressiveness of object literals for declaratively defining
> prototypal object models and permits simplifications of the proposed
> class declaration form.
Indeed. I really like this proposal.

David

[1] https://github.com/jquery/jquery/blob/master/src/core.js#L304
[2] https://github.com/jquery/jquery/blob/master/src/core.js#L368
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Allen Wirfs-Brock

On Jul 18, 2011, at 11:32 AM, Brendan Eich wrote:

> Hawt.
> 
> A bit rough in that LHS <& RHS mutates LHS, whereas LHS <| RHS is pure and 
> produces a new object (which could be optimized to mutate RHS, note well!). 
> Both <| and <& are operators, to support chaining. Would it be better for <& 
> to be pure as <| is, and make an assignment operator form, LHS <&= RHS, that 
> expands to LHS = LHS <& RHS?

One way to think about <& is as a more declarative and more concise alternative 
to Object.defineProperties. I think there are plenty of use causes for the 
mutating extends.  For example, adding properties to the prototype object of a 
function.  Another issue is that the object you need to extend may already have 
been captured somewhere.  For example, a super.constructor call might have 
registered the object in a WeakMap and if <& created a new instance you would 
loose the identify relationship.

In practice, I think most of the more declarative uses such as adding own 
properties can be implemented (and perhaps even specified) such that no extra 
objects need to be created.

One thing that I think is still open is whether the RHS needs to be an 
ObjectLiteral or whether any object producing expression should be allowed.  
All the use cases  I have explored use an ObjectLiteral but I don't see any 
hazard (like would be the case if <| mutated the LHS [[Prototype]]) with 
allowing a non-literal value of the RHS.

> 
> Anyway, if I have <& right, then:
> 
> class SkinnedMesh extends THREE.Mesh {
>  constructor(geometry, materials) {
>super(geometry, materials);
> 
>public identityMatrix = new THREE.Matrix4();
>public bones = [];
>public boneMatrices = [];
>...
>  }
> 
>  update(camera) {
>...
>super.update();
>  }
> }
> 
> from http://wiki.ecmascript.org/doku.php?id=harmony:classes would desugar to:
> 
> function SkinnedMesh(geometry, materials) {
>  return super(geometry, materials) <& {
>identityMatrix: new THREE.Matrix4(),
>bones: [],
>boneMatrices: [],
>...
>  };
> }
> 
> SkinnedMesh.prototype = THREE.Mesh.prototype <| {
>  update(camera) {
>...
>super.update();
>  }
> };

yes, plus you need a
   constructor: SkinnedMesh
in the object literal used to defined SkinnedMesh.prototype

> 
> Class-side inheritance could be done via
> 
> let SkinnedMesh = THREE.Mesh <| (function (geom, mats) { ... } <& { 
> classMethod() {...} });
> 
> This loses the hoisting of SkinnedMesh that the function declaration 
> desugaring gained "for free" -- another rough spot to smooth out.
> 
> There's still a usability argument for class syntax, certainly.

Perhaps, but a simpler class syntax is arguably a better class syntax and as I 
mentioned "static" properties are relatively rare.  If the class declaration is 
taking care of building both the class and instance side prototype chains then

class SkinnedMesh extends THREE.Mesh {
...
} <& {
classMethod() {...}
};

would take care of them without complicating the class declaration body.

> 
> Class syntax is also, for some folks, an attractive nuisance because of 
> single-inheritance OOP being oversold and very often the wrong paradigm. But 
> <& helps there too -- one can more conveniently make mixins (I must mean <&= 
> here, of course).
> 
> The last conflicting name wins, or so it seems from what you've written. The 
> compositional answer there is to seal properties you don't want anyone to 
> redefine by a conflicting extend operation. I'm assuming the internal method 
> used to update the LHS or populate the new copy of it is 
> [[DefineOwnProperty]], as with ES5 object literals, and not [[Put]].

   Exactly. Like I mentioned above, <& is I proposed it (your <&=) is 
essentially a syntactic shorthand for Object.defineProperties. 

Allen



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


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Bob Nystrom
On Mon, Jul 18, 2011 at 10:32 AM, Allen Wirfs-Brock 
wrote:
> This is a nice declarative way to describe the per instance state but it
turns out it doesn't generalize very well to multiple levels of inheritance.

This is an important point. I think the reason most OOP languages make a
distinction between object construction and initialization is because in the
presence of inheritance, you need 1 construction, but N initializations
where N is the depth of your inheritance chain. If you try to construct and
initialize in one step, it's hard to do that (as your proposal addresses).

> A similar issue exists for the proposed class declarations.  That proposal
includes the concept of "static" (a lot of us don't like that the term
"static" in this context)  property declaration:

Yeah, I don't think anyone is crazy about that keyword, but it's:

1. Reserved already.
2. Familiar from other languages and it works about the same here as it does
in those.

I liked "class" instead, but the worry about nested classes was enough to
talk me out of it.

We have a challenge with JS keywords:

1. We want to re-use keywords from other languages to make JS familiar and
to use what's already in the programmer's head. If some JS construct looks
and acts similar to a construct in other popular languages, using the same
word for it is like instant knowledge.

2. We want to emphasize JS's unique features. JS is not Java (or C++, or C#,
or Smalltalk, or Ruby) and we run the risk of leading users down a false
path if we make JS look superficially too much like them. There's also a
strong cultural bias where JS = light, terse, expressive, fun and Java =
verbose, rigid, work. Borrowing keywords from Java makes people worry that
there's going to be a JavaScript khaki dress code. Personally, I think
that's much ado about nothing, but I can understand why people would worry
that the suits are going to show up and crash the party.

> Static properties are really just own properties of the constructor
object.  While sometimes useful, they occur relatively infrequently yet they
require a additional declaration form within class bodies.

I just did some quick hunting through a few classes in the Closure library.
Instance methods are definitely the most common kind of member there, but
static methods were used in every type I looked at. For example,
goog.ui.Component has a static mutable field, three "constants" which are
properties on the constructor, and a couple of static methods.
goog.ui.Tooltip has five members that would use "static" in the class
proposal.

> This complicates the conceptual model of a class declaration by allowing
intermingling of constructor and prototype property declaration.

There can also be confusion between what goes on the prototype and what goes
on the new instance.

> This also increase the potential for confusion about the meaning of "this"
 (and "super") within such static property declarations.

Good point. From a conceptual simplicity argument, I like the idea of having
different curly blocks for "stuff on the ctor" and "stuff on the proto".
Pragmatically, though, C++, Java, and C# all mix instance and non-instance
members together and people seem to get by without too much trouble.

Looking at your example:

  class Point  {
private __validate(x,y) { return typeof x == 'number' && typeof y =
'number'};
constructor(x,y) {
  if (!this.__validate(x,y)) throw "invalid";
  return this <& {
  private __x: x,
  private __y: y
  };
   }
  } <& {
 get origin() { new this(0,0); }
  };

A few things stand out for me:

1. Personal preference, but it's pretty punctuation heavy.
2. It seems strange that the instance methods are in the class block, and
the methods on the class itself aren't. That feels backwards.
3. Unless I've had it explained to me, there's no way I could figure out
what that code means even if I'm an expert in other programming languages.

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


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Brendan Eich
On Jul 18, 2011, at 12:16 PM, Allen Wirfs-Brock wrote:

> On Jul 18, 2011, at 11:32 AM, Brendan Eich wrote:
> 
>> Hawt.
>> 
>> A bit rough in that LHS <& RHS mutates LHS, whereas LHS <| RHS is pure and 
>> produces a new object (which could be optimized to mutate RHS, note well!). 
>> Both <| and <& are operators, to support chaining. Would it be better for <& 
>> to be pure as <| is, and make an assignment operator form, LHS <&= RHS, that 
>> expands to LHS = LHS <& RHS?
> 
> One way to think about <& is as a more declarative and more concise 
> alternative to Object.defineProperties. I think there are plenty of use 
> causes for the mutating extends.  For example, adding properties to the 
> prototype object of a function.  Another issue is that the object you need to 
> extend may already have been captured somewhere.  For example, a 
> super.constructor call might have registered the object in a WeakMap and if 
> <& created a new instance you would loose the identify relationship.

Sure, I'm not saying word one against the mutating form -- just noting the 
symmetry break w.r.t. <| and suggesting a fix that builds on the assignment 
operator.


> In practice, I think most of the more declarative uses such as adding own 
> properties can be implemented (and perhaps even specified) such that no extra 
> objects need to be created.

Agreed.


> One thing that I think is still open is whether the RHS needs to be an 
> ObjectLiteral or whether any object producing expression should be allowed.  
> All the use cases  I have explored use an ObjectLiteral but I don't see any 
> hazard (like would be the case if <| mutated the LHS [[Prototype]]) with 
> allowing a non-literal value of the RHS.

Probably right; another symmetry break.

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


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Sean Eagan
On Mon, Jul 18, 2011 at 1:44 PM, Allen Wirfs-Brock
 wrote:
>> Also, how about |> as opposed to <&, since it is a dual to <| adding
>> own rather than inherited properties?
>
> I'd be a bit concerned about  some people getting confused about which 
> direction of the "arrow" corresponds to each operation.

I think the arrow-to-operator correspondence would be fairly easy to
remember... "extension arrows point back in space to prototypes which
exist back in time , and forward in space to own properties which will
exist forward in time".

>
> I like the nemonic value of having + or & as part of the operator symbol for 
> "extend" but  unfortunately <+ can't be used.

One thing to note is that <& would disallow using & as a unary
operator in the future.

Here's another option to consider:

// replace <| with <>
let B = A <> {...}; // looks like a (prototype) chain link
// then +> could make sense
let b = B +> {}; // "adding" pointed to properties.


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


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Brendan Eich
On Jul 18, 2011, at 1:39 PM, Sean Eagan wrote:

> On Mon, Jul 18, 2011 at 1:44 PM, Allen Wirfs-Brock
>  wrote:
>>> Also, how about |> as opposed to <&, since it is a dual to <| adding
>>> own rather than inherited properties?
>> 
>> I'd be a bit concerned about  some people getting confused about which 
>> direction of the "arrow" corresponds to each operation.
> 
> I think the arrow-to-operator correspondence would be fairly easy to
> remember... "extension arrows point back in space to prototypes which
> exist back in time , and forward in space to own properties which will
> exist forward in time".

Whatever happens, we mix metaphors:

1. <| is pointing in the reference direction of __proto__ aka [[Prototype]].

2. <& is pointing to the copy destination.

However, making the arrow point to the right mixes yet another metaphor:

3. +> or whatever points to the copy sources.

I do not think 3 helps as much as it hurts.

Separate point: left to right assignment or copy operation is confusing in many 
languages, and right to left is the norm. This goes back to assembly variants 
(gdb x86 vs. Intel ASM). JS uses right to left assignment direction. I think 
this must matter.


>> I like the nemonic value of having + or & as part of the operator symbol for 
>> "extend" but  unfortunately <+ can't be used.
> 
> One thing to note is that <& would disallow using & as a unary
> operator in the future.

Yup. No plans there.


> Here's another option to consider:
> 
> // replace <| with <>
> let B = A <> {...}; // looks like a (prototype) chain link

How so? That link is unidirectional. I don't buy it, and <> historically means 
not equal or unordered.


> // then +> could make sense
> let b = B +> {}; // "adding" pointed to properties.

See above.

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


Re: Array.prototype.concat result length (ES5.1)

2011-07-18 Thread liorean
> On 07/14/2011 10:04 AM, Allen Wirfs-Brock wrote:
>> It is probably a bug, because array index based operations generally warp
>> around to 0 at 2^32.

On 18 July 2011 19:51, Jeff Walden  wrote:
> Removing all the RangeError stuff, and making array indexes just
> non-negative integers,  would be nice for ES6 or similar.  I suspect
> changing that won't break anyone worth caring about, although I do know some
> people have taken the time to care about this in the past (mostly in a
> spec-nut way :-) ):
>
> http://hexmen.com/blog/2006/12/push-and-pop/

Hmm. That link has the following to say:
-
Steps 3 – 6 of push are a little ambiguous, and the specification
probably should have stated that repeated increments to n must be done
using 32-bit unsigned integer arithmetic – it’s kind-of implicit as n
is assigned the result of the internal ToUint32 operator. Using 32-bit
arithmetic leads to some strange edge-cases: when n overflows from
232-1 to 0, push will have set a property called 4294967295. This is
strange, as 429496795 is not an array index (as discussed above), but
at least it means the property-value will still be available after the
inevitable array-truncation (when length is set to some small value in
step 8.)


That is actually contrary to my reading of ECMA-262 3ed. intentions. I
assume 5 ed. has the same intentions, but I have not checked it. The
way I read those intentions is as you can see in the error I reported
in my comment to:

http://blogs.msdn.com/b/jscript/archive/2008/03/25/performance-optimization-of-arrays-part-i.aspx
(Opera fixed a different but related bug in the same algorithms in
Futhark to follow the correct handling (as I read the spec). Carakan
today I don't know about.)

For those not wanting to go searching for my comment and sifting
through that text: The algorithm in question uses ToUInt32 to convert
the value, but the storage is not as uint32 but as pretty much
everywhere in ECMAScript, Number, thus follows normal double
arithmetics. This is particularly of note as it means that it should
not wrap around - the purpose of the following parts of 15.4.5.1
[[Put]] (P, V):

12. Compute ToUint32(V).

13. If Result(12) is not equal to ToNumber(V), throw a RangeError exception.

14. For every integer k that is less than the value of the length
property of A but not less than Result(12), if A itself has a property
(not an inherited property) named ToString(k), then delete that
property.

15. Set the value of property P of A to Result(12).

is to, at step 13, catch the specific event of trying to exceed uint32
size with the length property and throw an error *instead of* wrapping
around and as a result of step 14 of above algorithm destroy
properties on the array. Wrapping around is an error, because ToUInt32
gives not a uint32 but a Number which can fit into a unit32 as result.
IIRC the 3ed. spec never uses any other number format than Number, it
only performs the operations to fit an input Number type into the
limitations of those other number types, into an output of Number
type.
-- 
David "liorean" Andersson
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Allen Wirfs-Brock

On Jul 18, 2011, at 11:26 AM, Dmitry A. Soshnikov wrote:

> On 18.07.2011 21:32, Allen Wirfs-Brock wrote:
>> 
>> I've recently been experimenting with coding both prototypal and class based 
>> object definitions using the various syntactic forms that are currently on 
>> the table.  Something has emerged from that which has surprised me.  I have 
>> never been a big fan of the "extend" method that is provided by a number of 
>> JavaScript frameworks. However, based upon my experiments I'm now think that 
>> something like extend solves several issues with the declarative object and 
>> class declarations that we have recently been discussing.
>> 
>> Just in case there is anyone on this list who isn't familiar with extend, 
>> here is a quick explanation. In most frameworks that support it, "extend" is 
>> invoked something like this: 
>>obj.extend(extensionObj)
>> It copies the own properties of  extensionObj and makes corresponding own 
>> properties for obj.
> 
> JFTR: object.extend(...) first appeared in Prototype.js and was borrowed 
> there from Ruby. In Ruby though, this method method is delegation-based (that 
> is, a hidden class is created which is inserted as a direct ancestor of the 
> object and the superclass of the hidden class is set to extending module). 
> That is, if something changes in the mixed module, the changes are reflected 
> on the object which extended it.
> 

...

> Perhaps ES wants also this approach. OTOH, "extend" practice is already 
> strongly used in JS and from this viewpoint it makes sense to make extending 
> with copying and not using delegation.

That would require at mutable [[Prototype]] which is something we have been 
trying to stay away from in TC39.

> 
> 
...
> Am I alone here who want to put a space after the methods in this proposal? 
> ;) It's like operators, really:

feel free to use one.  a space isn't syntactically significant in that 
position. 

...
> 
> 
>>   if (!this.__validate(x,y)) throw "invalid";
>>   return this <| {
>>   __x: x,
>>   __y: y
>>  }
>>   };
>> }
>> 
> 
> What's the reason we want back to desugared factories (with all this explicit 
> stuff, manual `return`, setting manually proto, etc) instead of improving 
> constructors syntax by forming them to classes? Is the syntax already 
> accepted for classes by the way? I remind again this syntactic form which 
> seems (for me?) more elegant 
> http://dmitrysoshnikov.com/scheme-on-coffee/class.html.

One of the design issues in the class proposals has been how to distinguish 
between prototype properties and per instance properties added by a 
constructor.  The current class proposal uses public/private declarations in 
the constructor for that purpose. This proposal of mine is suggesting that 
instead of adding special syntax just for constructors in class declarations we 
should consider adding a new operator (<&) with multiple uses that can also 
address the constructor use case.



...

> I'm really sorry, perhaps it's only for me, but all these examples seem to me 
> too cryptic in respect of syntax (even like Perl). All these `} <& {` seem 
> for me as a syntactic noise. I even better would like to see some longer but 
> humanized "extends" keyword. Maybe it's about the habit and perhaps later it 
> will become for me not so cryptic (after all I can accept -> #, {||}, etc. as 
> an alternative for `function`).
> 

I'm sympathetic  to the crypticness argument but I get just as many arguments 
on the other side of the issue when proposing keyword based extensions.
Also, it is generally harder (but not necessarily impossible) to add keyword 
operators then it is special character based operators.  Automatic semi-colon 
insertion gets in the way.
Consider:

var function extend() {};
var bar = foo
   extend ({y:20});

> E.g.
> 
> let foo = {x: 10}
> 
> // delegation-based extending
> let bar = foo extend {
>   y: 20;
> };
> 
> // copy-based extending
> bar.mixin({
>   z: 30
> });
> 
> Pity btw, that < is already borrowed and is a normal operator, we could use 
> it instead of <| which is not the best on different fonts.  value="Mayber a back arrow? <- " />

 foo <-bar  //   foo < (-bar)

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


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Allen Wirfs-Brock

On Jul 18, 2011, at 1:05 PM, Bob Nystrom wrote:

> On Mon, Jul 18, 2011 at 10:32 AM, Allen Wirfs-Brock  
> wrote:
> > This is a nice declarative way to describe the per instance state but it 
> > turns out it doesn't generalize very well to multiple levels of inheritance.
> 
> This is an important point. I think the reason most OOP languages make a 
> distinction between object construction and initialization is because in the 
> presence of inheritance, you need 1 construction, but N initializations where 
> N is the depth of your inheritance chain. If you try to construct and 
> initialize in one step, it's hard to do that (as your proposal addresses).
> 
> > A similar issue exists for the proposed class declarations.  That proposal 
> > includes the concept of "static" (a lot of us don't like that the term 
> > "static" in this context)  property declaration:
> 
> Yeah, I don't think anyone is crazy about that keyword, but it's:
> 
> 1. Reserved already.

But we are using it in a context where that isn't an issue.

> 2. Familiar from other languages and it works about the same here as it does 
> in those

Arguably it doesn't.  Java/C# static methods are not 
inherited/over-ridable...of course that leads to the issue of constructor-side 
inheritance.

> 
> I liked "class" instead, but the worry about nested classes was enough to 
> talk me out of it.
> 
> We have a challenge with JS keywords:
> 
> 1. We want to re-use keywords from other languages to make JS familiar and to 
> use what's already in the programmer's head. If some JS construct looks and 
> acts similar to a construct in other popular languages, using the same word 
> for it is like instant knowledge.

I don't think we have listed this as a design guideline anywhere.   If a 
word/constructor looks the same or even similar but has different semantics we 
have instance confusion rather than instant knowledge.

We don't have to look familiar to get people to use JavaScript.  They are going 
to use it regardless.  We may be past the point where these is much value in 
mimicking other languages.

> 
> 2. We want to emphasize JS's unique features. JS is not Java (or C++, or C#, 
> or Smalltalk, or Ruby) and we run the risk of leading users down a false path 
> if we make JS look superficially too much like them. There's also a strong 
> cultural bias where JS = light, terse, expressive, fun and Java = verbose, 
> rigid, work. Borrowing keywords from Java makes people worry that there's 
> going to be a JavaScript khaki dress code. Personally, I think that's much 
> ado about nothing, but I can understand why people would worry that the suits 
> are going to show up and crash the party.
> 
> > Static properties are really just own properties of the constructor object. 
> >  While sometimes useful, they occur relatively infrequently yet they 
> > require a additional declaration form within class bodies.
> 
> I just did some quick hunting through a few classes in the Closure library. 
> Instance methods are definitely the most common kind of member there, but 
> static methods were used in every type I looked at. For example, 
> goog.ui.Component has a static mutable field, three "constants" which are 
> properties on the constructor, and a couple of static methods. 
> goog.ui.Tooltip has five members that would use "static" in the class 
> proposal.

I was speaking primarily from Smalltalk experience.  Even though it had  very 
good tool support for class-side methods, there use is relatively rare. 
Certainly less than 5% of all methods particularly if you discount the 
class-side methods that implement and support the new method which is basically 
the Smalltalk equivalent of the normal constructor.

They certainly shouldn't be particularly inconvenient to define. But they 
aren't a central feature of OO design and probably don't deserve quite as much 
language design attention as instance methods. 

BTW, you may find some of the metric at 
http://www.emunix.emich.edu/~ahmad/metrdes.htm interesting.

> 
> > This complicates the conceptual model of a class declaration by allowing 
> > intermingling of constructor and prototype property declaration.
> 
> There can also be confusion between what goes on the prototype and what goes 
> on the new instance.

Exactly.  I'm arguing that placing instance properties in an extension object 
literal within the constructor is a way to reduce this confusion without adding 
new property declarations that can only occur in the function bodies of 
constructor functions.


> 
> > This also increase the potential for confusion about the meaning of "this"  
> > (and "super") within such static property declarations.
> 
> Good point. From a conceptual simplicity argument, I like the idea of having 
> different curly blocks for "stuff on the ctor" and "stuff on the proto". 
> Pragmatically, though, C++, Java, and C# all mix instance and non-instance 
> members together and people seem to get by without too much troub

Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Allen Wirfs-Brock

On Jul 18, 2011, at 1:37 PM, Brendan Eich wrote:

> On Jul 18, 2011, at 12:16 PM, Allen Wirfs-Brock wrote:
> 
>> On Jul 18, 2011, at 11:32 AM, Brendan Eich wrote:
>> 
>>> Hawt.
>>> 
>>> A bit rough in that LHS <& RHS mutates LHS, whereas LHS <| RHS is pure and 
>>> produces a new object (which could be optimized to mutate RHS, note well!). 
>>> Both <| and <& are operators, to support chaining. Would it be better for 
>>> <& to be pure as <| is, and make an assignment operator form, LHS <&= RHS, 
>>> that expands to LHS = LHS <& RHS?
>> 
>> One way to think about <& is as a more declarative and more concise 
>> alternative to Object.defineProperties. I think there are plenty of use 
>> causes for the mutating extends.  For example, adding properties to the 
>> prototype object of a function.  Another issue is that the object you need 
>> to extend may already have been captured somewhere.  For example, a 
>> super.constructor call might have registered the object in a WeakMap and if 
>> <& created a new instance you would loose the identify relationship.
> 
> Sure, I'm not saying word one against the mutating form -- just noting the 
> symmetry break w.r.t. <| and suggesting a fix that builds on the assignment 
> operator.

You're right it can be viewed that way.  Even though I know that = or += and 
friends are just operators I think I tend to think of them more like a 
statement form.  Also all the other assignment operators are operations upon 
values and they modify a variable rather than mutate an object.  I see where 
you're coming from on this but personally that lack of symmetry with the other 
assignment operators feels more disconcerting then the lack of symmetry with <|.


> 
> 
>> In practice, I think most of the more declarative uses such as adding own 
>> properties can be implemented (and perhaps even specified) such that no 
>> extra objects need to be created.
> 
> Agreed.
> 
> 
>> One thing that I think is still open is whether the RHS needs to be an 
>> ObjectLiteral or whether any object producing expression should be allowed.  
>> All the use cases  I have explored use an ObjectLiteral but I don't see any 
>> hazard (like would be the case if <| mutated the LHS [[Prototype]]) with 
>> allowing a non-literal value of the RHS.
> 
> Probably right; another symmetry break.

Yes, if the symmetry argument would be my primary reason for restricting the 
RHS.  But then <& could be use for things like:

Object.prototype.extend = function (obj) {this <& obj};


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


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Bob Nystrom
On Mon, Jul 18, 2011 at 3:40 PM, Allen Wirfs-Brock wrote:

>
> On Jul 18, 2011, at 1:05 PM, Bob Nystrom wrote:
>
> 2. Familiar from other languages and it works about the same here as it
> does in those
>
> Arguably it doesn't.  Java/C# static methods are not
> inherited/over-ridable...of course that leads to the issue of
> constructor-side inheritance.
>

I did say "*about* the same" and not *exactly* the same. Naturally there are
some differences, but there are plenty of similarities too. I don't think a
programmer from C++/C#/Java would find this astonishing at all, and would
probably have little trouble inferring what it means:

  class Point {
static zero() { return new Point(0, 0); }
  }

  var p = Point.zero();

1. We want to re-use keywords from other languages to make JS familiar and
> to use what's already in the programmer's head. If some JS construct looks
> and acts similar to a construct in other popular languages, using the same
> word for it is like instant knowledge.
>
> I don't think we have listed this as a design guideline anywhere.
>

Does it need to be written down as a guideline to be a good idea?


> If a word/constructor looks the same or even similar but has different
> semantics we have instance confusion rather than instant knowledge.
>
> We don't have to look familiar to get people to use JavaScript.  They are
> going to use it regardless.
>

That's probably true (yay browser lock-in) but I don't know that's what I'd
call a great attitude for usability. I'm imagining that as a bumper sticker.
JavaScript: you're going to use it regardless.

 We may be past the point where these is much value in mimicking other
> languages.
>

What makes you say that?


> I was speaking primarily from Smalltalk experience.  Even though it had
>  very good tool support for class-side methods, there use is relatively
> rare.
>

I'm not a Smalltalker but my impression is that Smalltalk culture was more
open to defining things as instance methods where a Javascripter would
likely make a static method on some constructor. Especially in recent years
where monkey-patching existing protos is considered bad form, that leads to
fewer instance methods and more static ones. Likewise, for-in loops
discourage adding methods on prototypes.

Even in Harmony, many of the new methods being adding are "static":
Proxy.create(), Proxy.createFunction(), Proxy.isTrapping(),
Object.getPropertyDescriptor(), Object.getPropertyNames(), Object.is(),
Number.isFinite(), Number.isNan()... If anything non-instance methods are
becoming more important in JS as time goes on (though modules might change
that).

Certainly less than 5% of all methods particularly if you discount the
> class-side methods that implement and support the new method which is
> basically the Smalltalk equivalent of the normal constructor.
>

My rough calculation was around 10% looking at Closure JS code.


> They certainly shouldn't be particularly inconvenient to define. But they
> aren't a central feature of OO design and probably don't deserve quite as
> much language design attention as instance methods.
>

Agreed.


> The primary purpose of a class is to define the behavior (methods) of
> instances. It is describing an abstraction over all the possible instances.
> The behavior of the singleton class object is typically secondary to the
> primary abstraction.
>

True, but secondary still matters.

> 3. Unless I've had it explained to me, there's no way I could figure out
> what that code means even if I'm an expert in other programming languages.
>
> Yes,but how long will it take you to learn it.  Isn't it better when
> learning something new to know that you don't understand it rather than to
> being mislead into thinking it is something familiar when it really isn't.
>

I don't like being led astray, certainly. Personally, I do like learning
"this is kinda like a foo" and then later having that refined to "but it
doesn't bar and it bazzes". I'd rather that than having to learn a new
concept from a blank page only to reach the end and realize "hey, this is
75% like a foo."

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


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Brendan Eich
On Jul 18, 2011, at 4:50 PM, Bob Nystrom wrote:

> On Mon, Jul 18, 2011 at 3:40 PM, Allen Wirfs-Brock  
> wrote:
> 
> On Jul 18, 2011, at 1:05 PM, Bob Nystrom wrote:
>> 2. Familiar from other languages and it works about the same here as it does 
>> in those
> Arguably it doesn't.  Java/C# static methods are not 
> inherited/over-ridable...of course that leads to the issue of 
> constructor-side inheritance.
> 
> I did say "about the same" and not exactly the same. Naturally there are some 
> differences, but there are plenty of similarities too. I don't think a 
> programmer from C++/C#/Java would find this astonishing at all, and would 
> probably have little trouble inferring what it means:
> 
>   class Point {
> static zero() { return new Point(0, 0); }
>   }
>   
>   var p = Point.zero();

Indeed, isn't that legal C# 4.0? :-P


> 
>> 1. We want to re-use keywords from other languages to make JS familiar and 
>> to use what's already in the programmer's head. If some JS construct looks 
>> and acts similar to a construct in other popular languages, using the same 
>> word for it is like instant knowledge.
> 
> I don't think we have listed this as a design guideline anywhere.
> 
> Does it need to be written down as a guideline to be a good idea?

Zing!

I've been on this side since ES4 days. I'm a bit older and wiser, so I'll just 
add that it takes nice judgment and experience to know when to imitate and when 
to diverge.

It's clear classes are not quite complete or coherent for ES.next, even though 
the proposal has been accepted (too many open issues, some not recorded). 
Imitating another language won't settle the open issues. We need to focus on 
specifics and simplify if possible, cut if necessary.


>  
> If a word/constructor looks the same or even similar but has different 
> semantics we have instance confusion rather than instant knowledge.
> 
> We don't have to look familiar to get people to use JavaScript.  They are 
> going to use it regardless.
> 
> That's probably true (yay browser lock-in) but I don't know that's what I'd 
> call a great attitude for usability. I'm imagining that as a bumper sticker. 
> JavaScript: you're going to use it regardless.

I'm with Bob here.

Word on the street, from folks ranging the skill gamut, is that <|, <& and so 
on are Perl-ish line noise. We should consider alternatives, even if it means 
restricted productions.


> The primary purpose of a class is to define the behavior (methods) of 
> instances. It is describing an abstraction over all the possible instances. 
> The behavior of the singleton class object is typically secondary to the 
> primary abstraction.
> 
> True, but secondary still matters.

Here you were arguing about class vs. prototype method indentation or body 
nesting level? I could see us making a subordinate body for class methods, 
instead of using 'static'.

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


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Bob Nystrom
On Mon, Jul 18, 2011 at 4:59 PM, Brendan Eich  wrote:

>  The primary purpose of a class is to define the behavior (methods) of
>> instances. It is describing an abstraction over all the possible instances.
>> The behavior of the singleton class object is typically secondary to the
>> primary abstraction.
>>
>
> True, but secondary still matters.
>
> Here you were arguing about class vs. prototype method indentation or body
> nesting level?
>

I think Allen was explaining why it makes sense for "static" methods to be
in a second curly block following the main class definition.

I could see us making a subordinate body for class methods, instead of using
> 'static'.


Interesting idea! Something like this?

class Point {
  constructor(x, y) {
this.x = x;
this.y = y;
  }

  manhattanDistance() {
return Math.abs(this.x) + Math.abs(this.y);
  }

  ??? {
zero() {
  return new Point(0, 0);
}

unit() {
  return new Point(1, 1);
}
  }
}

It looks a little strange to me to lump the class members together like that
and leave the prototype ones directly under class given that the prototype
members don't end up on the class. You could flip it around to:

class Point {
  constructor(x, y) {
this.x = x;
this.y = y;
  }

  zero() {
return new Point(0, 0);
  }

  unit() {
return new Point(1, 1);
  }

  prototype {
manhattanDistance() {
  return Math.abs(this.x) + Math.abs(this.y);
}
  }
}

Pros:
1. Makes it abundantly clear that prototype members are just that.
2. Makes it clearer (I think?) that members on the constructor ("class") are
that. Basically, the name of the surrounding curly ("prototype" or "class")
tells you where the member goes.

Cons:
1. Prototype members, the most common case, are the most verbose and suffer
two levels of indentation.
2. constructor() is in weird limbo. Should it be under prototype or class?
3. Lots'o'curlies.

There may be a good solution hiding in here somewhere, but I'm not sure.

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


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Brendan Eich
On Jul 18, 2011, at 5:31 PM, Bob Nystrom wrote:

> class Point {
>   constructor(x, y) {
> this.x = x;
> this.y = y;
>   }
> 
>   zero() {
> return new Point(0, 0);
>   }
> 
>   unit() {
> return new Point(1, 1);
>   }
> 
>   prototype {
> manhattanDistance() {
>   return Math.abs(this.x) + Math.abs(this.y);
> }
>   }
> }
> 
> Pros:
> 1. Makes it abundantly clear that prototype members are just that.

But that's not a good in itself, and your argument about many other languages 
putting "instance methods" at the level that this approach uses for class 
methods goes against.


> 2. Makes it clearer (I think?) that members on the constructor ("class") are 
> that. Basically, the name of the surrounding curly ("prototype" or "class") 
> tells you where the member goes.

This is a fair point but I think it is outweighed by the Cons (mine plus yours).


> Cons:
> 1. Prototype members, the most common case, are the most verbose and suffer 
> two levels of indentation.

That's a problem too (in addition to the strangeness compared to other 
languages with 'class' syntax).


> 2. constructor() is in weird limbo. Should it be under prototype or class?

It binds a prototype property (MyDate.prototype.constructor), absent more magic 
to make that alias. It does not bind a class property (e.g., 
MyDate.constructor).


> 3. Lots'o'curlies.

This is a pain, but so are lots o' statics -- but generally class methods are 
few, so it could be a wash.


> There may be a good solution hiding in here somewhere, but I'm not sure.


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


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Allen Wirfs-Brock

On Jul 18, 2011, at 4:50 PM, Bob Nystrom wrote:

> 
> 
> On Mon, Jul 18, 2011 at 3:40 PM, Allen Wirfs-Brock  
> wrote:
> 
> On Jul 18, 2011, at 1:05 PM, Bob Nystrom wrote:
>> 2. Familiar from other languages and it works about the same here as it does 
>> in those
> Arguably it doesn't.  Java/C# static methods are not 
> inherited/over-ridable...of course that leads to the issue of 
> constructor-side inheritance.
> 
> I did say "about the same" and not exactly the same. Naturally there are some 
> differences, but there are plenty of similarities too. I don't think a 
> programmer from C++/C#/Java would find this astonishing at all, and would 
> probably have little trouble inferring what it means:

But if you were coming from a language where constructors (classes) were real 
objects with real methods that could reference this and which were inherited by 
subclass object you might look at the issue quite differently

> 
>   class Point {
> static zero() { return new Point(0, 0); }
>   }

in fact you might look at the above zero method and say, Oh, that's buggy.  He 
didn't think about what will happen when somebody creates Point3D as a subclass 
and then codes:  Point3D.zero();

A better definition would be:

class Point {
static zero() { return new this(0, 0); }
  }
or, probably even better this:

class Point {
static zero() { return new this( ); }
  }

and you probably would want to make sure that the constructor always return the 
origin for the default no argument case.

The main point is that to do the right think here it is important to not think 
of it as being just like C++/C#/Java


>   
>   var p = Point.zero();
> 
>> 1. We want to re-use keywords from other languages to make JS familiar and 
>> to use what's already in the programmer's head. If some JS construct looks 
>> and acts similar to a construct in other popular languages, using the same 
>> word for it is like instant knowledge.
> 
> I don't think we have listed this as a design guideline anywhere.
> 
> Does it need to be written down as a guideline to be a good idea?

The real issue is what is both looks and acts similarly enough to make this a 
good rule to apply.  There is clearly some disagreement about this particular 
case and a hazard of this general rule.
>  
> If a word/constructor looks the same or even similar but has different 
> semantics we have instance confusion rather than instant knowledge.
> 
> We don't have to look familiar to get people to use JavaScript.  They are 
> going to use it regardless.
> 
> That's probably true (yay browser lock-in) but I don't know that's what I'd 
> call a great attitude for usability. I'm imagining that as a bumper sticker. 
> JavaScript: you're going to use it regardless.

I wasn't trying to make a statement about usability.  I actually think 
usability (and readability) of language features is very important.  But I'm 
more concerned about the long term usability of the language by people who know 
the language well then I am about short term ease of adoption by somebody today 
who is knowledgeable about some in a legacy language. JavaScript is here and 
and going to remain here for a very long time.  I want it to hold together on 
its own terms and to be most usable for people for whom it is their first and 
primary programming language.

> 
>  We may be past the point where these is much value in mimicking other 
> languages.
> 
> What makes you say that?

JavaScript is its own unique combination of concepts and features. I think that 
some of the more significant warts in JavaScript (including the new operator, 
instanceof, and some aspects of constructor functions) are a direct result of 
such mimicry.  Rather than continuing to just graft on features from other 
language we need to be evolving JavaScript on its own terms.  This needs to be 
informed by knowledge of the successes and failures of other language designs 
and many other things.   But I see little value in mimicry for its own sake.


>  
> I was speaking primarily from Smalltalk experience.  Even though it had  very 
> good tool support for class-side methods, there use is relatively rare.
> 
> I'm not a Smalltalker but my impression is that Smalltalk culture was more 
> open to defining things as instance methods where a Javascripter would likely 
> make a static method on some constructor. Especially in recent years where 
> monkey-patching existing protos is considered bad form, that leads to fewer 
> instance methods and more static ones. Likewise, for-in loops discourage 
> adding methods on prototypes.

This may well be the case, but is it something we want to encourage for the 
next 50 years? Most behavior belongs on instances because it is the instance 
that model the computation system of the program.  Instances are what OO design 
and programming is all about.  If we make it easy to define instance behavior 
and harder to define "static" behavior that is probably a good think in the 
long run.

Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Allen Wirfs-Brock

On Jul 18, 2011, at 4:59 PM, Brendan Eich wrote:

> 
> Word on the street, from folks ranging the skill gamut, is that <|, <& and so 
> on are Perl-ish line noise. We should consider alternatives, even if it means 
> restricted productions.

As I've said in the past, I'm generally more in the COBOL/readability camp than 
I am in the APL/terseness  camp (in reality, I more of a PL/I guy.  (and what's 
this new fangled Perl thing that everybody keeps talking about??))

That said, in writing sample code I've come to find <| to be rather pleasant to 
both write and read. 

Beyond that, we need to really decide what we want to surface syntax of JS to 
be like as it evolve.  Do we want a keyword rich language or a concise language 
that uses lots of special characters.  How to we find the balance between the 
extreme.  For now I don't think we really have anything to guide us so we keep 
oscillate  from on to the other based upon the latest feedback on a proposal 
that goes one way or the other.

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


An "extend" operator is a natural companion to <|

2011-07-18 Thread Axel Rauschmayer
> From: Allen Wirfs-Brock 
> Date: July 18, 2011 19:32:24 GMT+02:00
> To: es-discuss 
> Subject: An "extend" operator is a natural companion to <| 


Definitely a nice dual to <|

> proto <| obj


What happens if obj is not a literal? Then it would make sense to do a shallow 
copy of obj whose prototype is proto. That would be useful for combining 
objects into a chain.

From your examples, it looks as if the lhs would be modified, a bit similar to 
the += operator. Then the "arrow" should probably point in the opposite 
direction, e.g.:

> objToBeModified +> increment


Quoting from your examples:

> function Point(x,y) {
>return tthis <& {
>   __x: x,
>   __y: y
>  };
> };
> Point.prototype <& {
>__validate(x,y) { return typeof x == 'number' && typeof y = 'number'}
> };


I love how the prototype is incremented here. What does "tthis" do? Wouldn't 
point simply return an object literal (no "this <&")?

Another example from your message:

> const Point = {
>  //private members
>  __x: 0,
>  __y: 0, 
>  __validate(x,y) { return typeof x == 'number' && typeof y = 'number'},
>  //public members
>  new(x,y) {
>   if (!this.__validate(x,y)) throw "invalid";
>   return this <| {
>   __x: x,
>   __y: y
>  }
>   };
> }

If things are ever done this way, I would prefer to have an initialize() method 
(that only initializes an instance that has been created for it) and not a 
method that instantiates and initializes at the same time. initialize() works 
together very well with super-references, because in subclasses, you simply 
call the super-initialize method.

-- 
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: An "extend" operator is a natural companion to <|

2011-07-18 Thread Axel Rauschmayer
> From: Bob Nystrom 
> Date: July 19, 2011 2:31:48 GMT+02:00
> To: Brendan Eich 
> Cc: es-discuss 
> Subject: Re: An "extend" operator is a natural companion to <|

To me, the important thing with class literals is to use naming consistently. 
If the class is named Point and you want to add properties to it, it seems odd 
to use an operator to add those properties to (what looks like) a method called 
"constructor". Under the hood, it makes sense. Superficially (with a sugared 
eye), it’s confusing.

> You could flip it around to:
> 
> class Point {
>   constructor(x, y) {
> this.x = x;
> this.y = y;
>   }
> 
>   zero() {
> return new Point(0, 0);
>   }
> 
>   unit() {
> return new Point(1, 1);
>   }
> 
>   prototype {
> manhattanDistance() {
>   return Math.abs(this.x) + Math.abs(this.y);
> }
>   }
> }


I kind of like the idea of parameterized object literals. But then I have no 
idea where class properties would go:

class Point(x,y) {
x: x,
y: y,
prototype {
manhattanDistance() {
return Math.abs(this.x) + Math.abs(this.y);
}
}
}

-- 
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: An "extend" operator is a natural companion to <|

2011-07-18 Thread Brendan Eich
On Jul 18, 2011, at 6:50 PM, Allen Wirfs-Brock wrote:

>> Even in Harmony, many of the new methods being adding are "static": 
>> Proxy.create(), Proxy.createFunction(), Proxy.isTrapping(), 
>> Object.getPropertyDescriptor(), Object.getPropertyNames(), Object.is(), 
>> Number.isFinite(), Number.isNan()... If anything non-instance methods are 
>> becoming more important in JS as time goes on (though modules might change 
>> that).
> 
> Brendan and I recently had a discussion about some of these and it isn't 
> clear that they are all in the correct places.  Of the ones you mentioned, 
> I'm not so sure I would call Proxy a constructor.  (you never say, new 
> Proxy() right?) it is really a factory object which means the methods you 
> name are instance side.

No, rather Proxy is a module name. We could even spec it for ES.next as 
something users must import from a standard library MRL:

  module Proxy from "@proxy";

and avoid polluting the global scope with 'Proxy' -- users get to name the 
module. With ES.next modules, one can even selectively import:

  import createFunction from "@proxy";


> The Object refection methods were put on object because it was a convenient  
> "namespace" object. But that's not a style I would want to encourage for 
> complex user applications.

It depends on whether we have set a precedent, and also on the domain type (see 
below).


> isFinite and isNaN probably should go on the instance side.

No, that requires an extra test, as we discussed re: isGenerator. These are 
intentional any -> boolean non-coercing functions, not methods. They must be 
callable on any type of argument without testing that the argument is a number 
and then using it to call a method.

/be

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


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Brendan Eich
On Jul 18, 2011, at 7:00 PM, Allen Wirfs-Brock wrote:

> On Jul 18, 2011, at 4:59 PM, Brendan Eich wrote:
> 
>> 
>> Word on the street, from folks ranging the skill gamut, is that <|, <& and 
>> so on are Perl-ish line noise. We should consider alternatives, even if it 
>> means restricted productions.
> 
> As I've said in the past, I'm generally more in the COBOL/readability camp 
> than I am in the APL/terseness  camp (in reality, I more of a PL/I guy.  (and 
> what's this new fangled Perl thing that everybody keeps talking about??))
> 
> That said, in writing sample code I've come to find <| to be rather pleasant 
> to both write and read. 

I can believe that. We should in any case not rush to judgment. "consider 
alternatives" means writing some side-by-side examples, playing with 
alternatives in practical code.


> Beyond that, we need to really decide what we want to surface syntax of JS to 
> be like as it evolve.  Do we want a keyword rich language or a concise 
> language that uses lots of special characters.  How to we find the balance 
> between the extreme.  For now I don't think we really have anything to guide 
> us so we keep oscillate  from on to the other based upon the latest feedback 
> on a proposal that goes one way or the other.

The main feedback is "don't grow the surface syntax too much". ES4 did 
overreach here, based on original-JS2/ES4 precedent and AS3. We should in any 
case not add "too much" (to be defined).

/be

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


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Rick Waldron
Hey Bob, FWIW...


> class Point {
>   constructor(x, y) {
> this.x = x;
> this.y = y;
>   }
>
>   zero() {
> return new Point(0, 0);
>   }
>
>   unit() {
> return new Point(1, 1);
>   }
>
>   prototype {
> manhattanDistance() {
>   return Math.abs(this.x) + Math.abs(this.y);
> }
>   }
> }
>

...That's actually the nicest, most intuitively designed "class" structure
I've seen so far.

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


Re: An "extend" operator is a natural companion to <|

2011-07-18 Thread Brendan Eich
On Jul 18, 2011, at 9:02 PM, Rick Waldron wrote:

> Hey Bob, FWIW...
> 
> 
> class Point {
>   constructor(x, y) {
> this.x = x;
> this.y = y;
>   }
> 
>   zero() {
> return new Point(0, 0);
>   }
> 
>   unit() {
> return new Point(1, 1);
>   }
> 
>   prototype {
> manhattanDistance() {
>   return Math.abs(this.x) + Math.abs(this.y);
> }
>   }
> }
> 
> ...That's actually the nicest, most intuitively designed "class" structure 
> I've seen so far.

This is actually close to a less magical syntax that flips around the 
"ClassElements" (immediate children of the class {...} container) to specify 
class methods. Here's a less sugared version:

class Point {
  zero() {
return new Point(0, 0);
  }

  unit() {
return new Point(1, 1);
  }

  prototype: {
constructor(x, y) {
  this.x = x;
  this.y = y;
}

manhattanDistance() {
  return Math.abs(this.x) + Math.abs(this.y);
}
  }
}


Notice how constructor is in the prototype object, as in JS with constructors 
and prototypes. Also, prototype: {...} not prototype {...}.

As Bob noted, though, even in JS and moreso (from Allen's stats) in Smalltalk, 
class methods are uncommon compared to prototype methods. Do you really want an 
extra level of indentation for the latter?

This example is skewed away from norms by having two class methods to one 
prototype method. I think constructor was mislocated, and when I fixed it just 
above, the instance- vs. class-method counts matched. Still unrealistic, though.

If we want *more* magic from the class syntax, not less, we could use 'new' at 
the outer class-element indentation level to declare the constructor, and 
automagically impute 'constructor' in the prototype from it. But we'd still be 
over-indenting the prototype methods, which are many, compared to the class 
methods (few). What was that Spock said about the needs of the many?

/be

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