Re: time to trim mustache

2012-06-06 Thread Brandon Benvie
Object.decorate seems to fit the bill I think.

On another note, using an array and the as of yet non-standardized but
still useful function name property is a lot more palatable and succinct
and is much closer to the desired improved object literal syntax. I've been
partial to the following reimagining of Object.extend as Object.decorate
which supports arrays of named functions as well as objects and also
setters/getters which existing extend functions don't support usually.

  Object.defineProperty(Object, 'decorate', {
configurable: true,
writable: true,
value: function decorate(o){
  var a, b, c, d;
  for (a in arguments) {
if (a) {
  if (Array.isArray(b = arguments[a])) {
// array of named functions
for (c = 0; c  b.length; c++) {
  if (typeof b[c] === 'function'  b[c].name) {
Object.defineProperty(o, b[c].name, { value: b[c],
configurable: true, writable: true });
  }
}
  } else {
// object
for (c in b) {
  // use getDesc instead of hasOwn to support get/set
  if (d = Object.getOwnPropertyDescriptor(b, c)) {
if (d.get || d.set) {
  Object.defineProperty(o, c, d);
} else {
  // purposefully trigger accessors if they exist
  o[c] = d.value;
}
  }
}
  }
}
  }
  return o;
}
  });
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: time to trim mustache

2012-06-05 Thread Irakli Gozalishvili
I just want to (re)express my (and many others) concern about new syntax.  
While Object.extend adds useful feature (Although I think Object.define would 
be more appropriate name) I don't think new syntax is really necessary. I do 
think that new syntax needs a lot more justification then new semantics. I also 
would argue that it's a good idea to alway make syntax changes in a separate 
iteration from the one where associated semantics have being introduced. That 
would allow both community and come tee to see these semantics in practice and 
having more knowledge to decide what syntax sugar would work best, if any new 
syntax even will turn out to be necessary.
 
 
  
 
 One of these things is installing private named properties upon an existing 
 object.  As currently specified, those could not be communicated to an extend 
 function via an object literal because we have disallowed any form of 
 refection upon private named properties. Object.extend could not see them on 
 the literal object in order to copy them.  Trying to solve this problem by 
 saying that Object.extend has special reflection privileges would violate the 
 encapsulation that the non-relection on private name properties was intended 
 to provided.  



But many other variations of this would do the job as well without a new syntax:

Object.extend(target, privates(
   name1, value1,
   name2, value2
))

 
 Anther ES6 specific semantic that has always been part of the mustache 
 proposal is the correct binding of methods with super references. I've 
 described this many times. So I'll just describe it again other than to 
 reinforce that mustache is the great way to dynamically associate super 
 referencing method to an object without running into the pitfalls that arise 
 with the defineMethod alternative. I see how with mustache we can live 
 without defineMethld.


But omitting reflection APIs is pretty dangerous path to go with IMO. JS has 
being great as it was always possible to fix things that were not working for 
you. I have feeling that providing semantics only through new syntax may take 
away this great power of JS.

Regards
--
Irakli Gozalishvili
Web: http://www.jeditoolkit.com/


On Monday, 2012-06-04 at 09:45 , Brendan Eich wrote:

 Kevin Smith wrote:
  Thanks Dave,
  
  Of the 3 use cases you mentioned, I think unique names are probably 
  sufficient for 1 and 3. For the second use case (an inaccessible 
  piece of data associated with an object), would not a weak map also be 
  appropriate?
  
 
 
 No, WeakMaps have two problems we've covered in this list:
 
 1. Less efficient than private names.
 
 This matters when you can least afford it, and it matters for private 
 names used to program in the large using objects in JS. WeakMaps require 
 special GC handling and they're an extra object with internal mutable 
 state. Private name objects are flat, frozen, and can be optimized a lot 
 harder.
 
 2. You cannot abstract property access:
 
 function get(obj, prop) { return obj[prop]; }
 
 works with a private name object referenced by prop. No such abstraction 
 can be done with a weak map.
 
 /be
 ___
 es-discuss mailing list
 es-discuss@mozilla.org (mailto: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: time to trim mustache

2012-06-05 Thread T.J. Crowder
On 5 June 2012 21:30, Irakli Gozalishvili rfo...@gmail.com wrote:

 I just want to (re)express my (and many others) concern about new syntax.  
 While
 Object.extend adds useful feature (Although I think Object.define would be
 more appropriate name) I don't think new syntax is really necessary. I do
 think that new syntax needs a lot more justification then new semantics.


Sorry, do you mean the new `Name` object stuff? (
http://wiki.ecmascript.org/doku.php?id=harmony:private_name_objects) Or...?
Still finding my feet, but not seeing any private stuff in AWB's extension
literals (except by association with `Name` objects).

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


Re: time to trim mustache

2012-06-05 Thread Allen Wirfs-Brock

On Jun 5, 2012, at 1:30 PM, Irakli Gozalishvili wrote:

 I just want to (re)express my (and many others) concern about new syntax.  
 While Object.extend adds useful feature (Although I think Object.define would 
 be more appropriate name) I don't think new syntax is really necessary. I do 
 think that new syntax needs a lot more justification then new semantics. I 
 also would argue that it's a good idea to alway make syntax changes in a 
 separate iteration from the one where associated semantics have being 
 introduced. That would allow both community and come tee to see these 
 semantics in practice and having more knowledge to decide what syntax sugar 
 would work best, if any new syntax even will turn out to be necessary.
  
 One of these things is installing private named properties upon an existing 
 object.  As currently specified, those could not be communicated to an 
 extend function via an object literal because we have disallowed any form of 
 refection upon private named properties. Object.extend could not see them on 
 the literal object in order to copy them.  Trying to solve this problem by 
 saying that Object.extend has special reflection privileges would violate 
 the encapsulation that the non-relection on private name properties was 
 intended to provided.  
 
 But many other variations of this would do the job as well without a new 
 syntax:
 
 Object.extend(target, privates(
name1, value1,
name2, value2
 ))
 

I'm not exactly sure what you privates function returns (which is the actual 
value that is passed to extend) but it can't be an object where name1 and name 
2 are property names because the current rules of private name enumerations 
would prevent them from being enumerated. Also I'm assuming that in a typical 
case you will want to install a related set of public and private methods on an 
object.

I guess you might express this as:

const private1 = new Name;
const private2 = new Name;
const private3 = new Name;
Object.extend(target, {
  publicMethod1() {...this[private3]...},
  publicMethod2() {...this[private2]()...},
  publicDate1: 42,
  get publicGet () {return this[private1]}
});
Object.extend(target, privates(  //assume private returns a object kind known 
to Object.extend that is capable of iterating over the name values it was 
constructed with
   private1,  undefined,  //private1 need to be a data valued property, not a 
method .  Let's assume that any non-function value is an indication of that 
intent
   private2, function(x) {...this[private1]...},  //note that traditional 
function declaration must be used. = doen' t have dynamic this and  concise 
methods are not available here
   private3, accessor({get: function() {return 
this[private2](this[private1])}})   //accessor produces some sort of 
descriptors that identifies the need to add an accessor property
});

more likely you would want to get it all into a single extend call, perhaps by 
making the privates be an additional argument or perhaps you intended this 
version of extends to support multiple arguments.  In either case you would 
have 

const private1 = new Name;
const private2 = new Name;
const private3 = new Name;
Object.extend(target, {
  publicMethod1() {...this[private3]...},
  publicMethod2() {...this[private2]()...},
  publicDate1: 42,
  get publicGet () {return this[private1]}
  },  
  privates(  //assume private returns a object of kind known to 
Object.extend that is capable of enumerating the name values it was 
constructed with
   private1,  undefined,  //private1 needs to be a data valued 
property, not a method .  Let's assume that any non-function value is an 
indication of that intent
   private2, function(x) {...this[private1]...},  //note that 
traditional function declaration must be used. = doen' t have dynamic this and 
 concise methods are not available here
   private3, accessor({get: function() {return 
this[private2](this[private1])}})   //accessor produces some sort of descriptor 
that identifies the need to add an accessor property
  )
);

In either case, once you have to start defining helper functions that generate 
argument descriptors like above, I don't see a lot of advantage over using 
Object.defineProperty/defineProperties:

const private1 = new Name;
const private2 = new Name;
const private3 = new Name;
Object.defineProperties(target, {
  publicMethod1: {value: function() {...this[private3]...}, configurable: 
true},
  publicMethod2: {value: function() {...this[private2]()...}, configurable: 
true}
  publicDate1: {value:42, enumerable: true, writable: true, configurable: 
true},
  publicGet : {get: function () {return this[private1]}, enumerable: true, 
writable: true, configurable: true}
  };
//private name properties probably can't use defineProperties because of the 
private name reflection probation 
Object.defineProperty(target, private1,   {value:undefined, 

Re: time to trim mustache

2012-06-04 Thread Kevin Smith
Thanks Dave,

Of the 3 use cases you mentioned, I think unique names are probably
sufficient for 1 and 3.  For the second use case (an inaccessible piece of
data associated with an object), would not a weak map also be appropriate?

So far I don't see that the benefit of private names (as opposed to just
unique names) outweighs the additional object model complexity.  As far as
I can tell, all of the use cases for private names can be addressed with
unique names and weak maps.  Am I wrong?

Regards,

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


Re: time to trim mustache

2012-06-04 Thread Brendan Eich

Kevin Smith wrote:

Thanks Dave,

Of the 3 use cases you mentioned, I think unique names are probably 
sufficient for 1 and 3.  For the second use case (an inaccessible 
piece of data associated with an object), would not a weak map also be 
appropriate?


No, WeakMaps have two problems we've covered in this list:

1. Less efficient than private names.

This matters when you can least afford it, and it matters for private 
names used to program in the large using objects in JS. WeakMaps require 
special GC handling and they're an extra object with internal mutable 
state. Private name objects are flat, frozen, and can be optimized a lot 
harder.


2. You cannot abstract property access:

  function get(obj, prop) { return obj[prop]; }

works with a private name object referenced by prop. No such abstraction 
can be done with a weak map.


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


Re: time to trim mustache

2012-06-01 Thread Allen Wirfs-Brock
On May 31, 2012, at 10:26 PM, David Herman wrote:

 It's become clear to me that mustache syntax is not well motivated. As a 
 simple update for objects, there's little it can do that Object.extend 
 couldn't do.

Probably not surprisingly, I strongly disagree. 

First, WRT motivation.  It's motivation is almost exactly that of object 
literals.  In classic JavaScript, there is nothing that an object literal can 
do that can't be done with multiple imperative steps using the  new operator, 
assignment expressions, Object.defineProperty calls (for accessor properties), 
etc.  Yet many JS programmer greatly prefer using an object level to describe 
construction of a singleton object over using such discrete imperative steps, 

In JavaScript: The Good Parts, Crock even lists object literals as one of the 
beautiful features of JavaScript.  The are arguably the best way to describe 
singleton objects in JavaScript.

The motivation for mustache is the same but applied to extending the structure 
of a pre-existing object in a pleasant and concise manner that does not require 
multiple imperative steps. There are many situations where it is necessary to 
add a package of properties to a pre-allocated object:  defining the properties 
for the prototype object that is automatically created for a constructor 
function, adding instance specific properties to an instance object within a 
constructor;  adding constructor properties to a constructor function; 
attaching methods to the pure data trees created by JSON.parse,  adding client 
specific properties  to any object returned from a library constructor, etc.

In ES6, with maxmin classes we will also have the need to added instance 
properties within a class constructor and to add class-side properties to a 
class as these are not currently directly support by the proposed class 
definition syntax.

These can (and now are) all done in multiple imperative steps. Mustache allows 
all of these sorts of object extensions to be accomplished using the exact same 
beautiful object literal syntax.  

Of course you can argue that, you would get the same thing via an Object.extend 
function with an object literal passed as an argument.  On a purely functional 
basis, that is true, for ES5 level semantics. However,  I argue that this lacks 
the concise beauty of mustache.

However, when we move into ES6 there are things that we have not yet figured 
out how to accomplish with an extends function but which simply fall out of 
mustache's design.  

One of these things is installing private named properties upon an existing 
object.  As currently specified, those could not be communicated to an extend 
function via an object literal because we have disallowed any form of refection 
upon private named properties. Object.extend could not see them on the literal 
object in order to copy them.  Trying to solve this problem by saying that 
Object.extend has special reflection privileges would violate the encapsulation 
that the non-relection on private name properties was intended to provided.  It 
would permit any agent to use Object.extend to copy private name properties 
(include properties that are  intended to server as type brands from any 
object to any other object.

Anther ES6 specific semantic that has always been part of the mustache proposal 
is the correct binding of methods with super references. I've described this 
many times.  So I'll just describe it again other than to reinforce that 
mustache is the great way to dynamically associate super referencing method to 
an object without running into the pitfalls that arise with the defineMethod 
alternative. I see how with mustache we can live without defineMethld.  I don't 
see howwithout defineMethod we can live without super binding mustache.

There is strong motivation for mustache and there are important things it can 
do that are not currently addressed by any Object.extend proposal that I have 
seen.
  
 I thought with my cascades proposal that it might gain more justification (to 
 allow the fluent aka chainable style even for methods that return void 
 instead of `this`), but even that's fairly weak tea. And we haven't even 
 really discussed what semantics it should have for nested objects: replace 
 (aka shallow) or recursively update (aka deep)?

To me, cascades where never an essential use case for mustache.  I think 
mustache have plenty of justification as originally proposed. I was happy to 
explore extending it to encompass the cascade use cases but the fact that those 
extensions  seem to result in seeming insurmountable issues doesn't relate to 
the original unextended mustache proposal.

(BTW, I think the semantics for nest cascades is pretty obvious. But won't 
sidetrack on it here).

 
 This debate over mustache/cascade/etc just isn't a worthwhile use of time. 
 And it's not on target for ES6 anyway. It's time to set this aside and just 
 focus on standardizing an Object.extend API (or possibly 

Re: time to trim mustache

2012-06-01 Thread Kevin Smith
Hi Allen,

I agree with your sentiments on the usefulness of mustache with respect to
extending an object, but I think the point that brings it down is the
fact that it will confuse developers with the put/define distinction.  It
just looks too much like batch assignment.

Cascade (or the more specific batch-assignment) would be useful, but
whether the gain in usefulness is worth the added language complexity is
something that would need to be quantified.  My hunch is that batch
assignment would only provide a minor improvement.

Regarding super references outside of class bodies:  I agree with Luke that
this is a foot gun.  The class body provides an easy to understand meaning
for super.  Outside of the class body, that meaning is going to be subtle,
probably too subtle to be worth it.  When adding methods to objects, we can
always just create an explicit variable to hold the super reference.

Regarding private names:  I'm not convinced that private, non-reflective
names are unproblematic in and of themselves.  I would personally like to
see more exploration on this front, with concrete use-cases.  What useful
things can we do with private names that we cannot do with globally unique
names?

Regards,

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


Re: time to trim mustache

2012-06-01 Thread David Herman
On Jun 1, 2012, at 8:52 AM, Kevin Smith wrote:

 Regarding private names:  I'm not convinced that private, non-reflective 
 names are unproblematic in and of themselves.  I would personally like to see 
 more exploration on this front, with concrete use-cases.  What useful things 
 can we do with private names that we cannot do with globally unique names?

Briefly, some high-level rationale:

// -

1. Paving cowpaths: Crockford's closures-for-private-properties pattern but 
without the per-instance costs:

function CrockClass() {
var myPrivateData = ...;
// one copy per instance
this.myMethod = function(...) {
... myPrivatedata ...
}
}

// versus:

var myPrivateName = new Name();
function ES6Class() {
this[myPrivateName] = ...;
}
ES6Class.prototype.myMethod = function(...) {
... this[myPrivateName] ...
}

2. Untamperable object properties:

var score = new Name(); // no cheating from the console!
function GamePlayer() {
this[score] = 0;
}

3. Classes that are easier to subclass without name clash concerns:

// super.js
var myPrivateName = new Name();
function MySuperClass() {
this[myPrivateName] = ...;
}

// sub.js
var myPrivateName = new Name();
function MySubClass() {
this[myPrivateName] = ...; // no clash :)
}

// -

I agree that unique is often private enough. I still favor private names that 
can either be unique or private depending on your needs. And maybe they should 
default to unique, not to private. But it should still be easy to make them 
truly private. For cases where you truly need robust information hiding, 
private names are more ergonomic than closures.

Dave

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


Re: time to trim mustache

2012-06-01 Thread Tab Atkins Jr.
On Fri, Jun 1, 2012 at 10:16 AM, David Herman dher...@mozilla.com wrote:
 1. Paving cowpaths: Crockford's closures-for-private-properties pattern but 
 without the per-instance costs:

 function CrockClass() {
    var myPrivateData = ...;
    // one copy per instance
    this.myMethod = function(...) {
        ... myPrivatedata ...
    }
 }

 // versus:

 var myPrivateName = new Name();
 function ES6Class() {
    this[myPrivateName] = ...;
 }
 ES6Class.prototype.myMethod = function(...) {
    ... this[myPrivateName] ...
 }

By the way, I just wrote a more-or-less real-life example for this
yesterday, to help Hixie with speccing something in HTML:
http://www.xanthir.com/blog/b4JB0

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


Re: time to trim mustache

2012-06-01 Thread David Herman
On Jun 1, 2012, at 12:26 AM, Allen Wirfs-Brock wrote:

 These can (and now are) all done in multiple imperative steps. Mustache 
 allows all of these sorts of object extensions to be accomplished using the 
 exact same beautiful object literal syntax.  

A beautiful syntax for something that can be done with a single function call 
an an object literal is *very* weak motivation. Syntax isn't cheap. I probably 
need to write a blog post about this. For syntax to be worth adding, it has to 
clear a higher bar than API's. If we can write an API that does something 
perfectly well and a new syntax only saves a handful of characters, it's not 
enough.

 Of course you can argue that, you would get the same thing via an 
 Object.extend function with an object literal passed as an argument.  On a 
 purely functional basis, that is true, for ES5 level semantics. However,  I 
 argue that this lacks the concise beauty of mustache.

An analogy: you could say the same thing about keyword arguments; writing

f(width: 320, height: 240)

is arguably more beautiful than

f({ width: 320, height: 240 })

because the language is saying exactly what you mean without need for 
boilerplate. But that boilerplate is only two characters, so it's not worth the 
additional language complexity to add support for it. Another analogy: 
Smalltalk gets along great with using blocks for control abstractions because, 
again, it's only two skinny little characters of boilerplate.

 One of these things is installing private named properties upon an existing 
 object.  As currently specified, those could not be communicated to an extend 
 function via an object literal because we have disallowed any form of 
 refection upon private named properties.

We dropped computed property names in object literals, so we don't even have 
any way of putting private names on an object literal anyway. The sets of 
things that you could express with mustache but not with Object.extend is fast 
dwindling for ES6.

 This debate over mustache/cascade/etc just isn't a worthwhile use of time. 
 And it's not on target for ES6 anyway. It's time to set this aside and just 
 focus on standardizing an Object.extend API (or possibly two, one for 
 shallow, one for deep).
 Worthwhileness is simply your opinion, not mine. Anything we collectively 
 decide we need in ES6 can be in ES6.

Mustache was demoted to strawman. Proposals in strawman are not accepted for 
ES6. We can certainly break our own process if we need to, but it provides a 
useful check on moving too fast. If there's anything we should be careful 
about, it's new syntax. Again, I need to write a blog post about this.

 Object.extend is also not currently proposed for ES6 so I don't see how you 
 can argue that it is more on target .

It's not. We can certainly *discuss* things that are not on target for ES6, and 
I claim that Object.extend is something that would be of more value for us to 
discuss now, because as soon as we come to some agreement, developers can 
polyfill it and use it immediately. We should pave that cowpath because it's 
the more immediately solvable problem, regardless of whether it ends up in ES6.

Dave

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