Re: Minimalist (why) classes ?

2011-11-13 Thread Axel Rauschmayer
Good point. Note that you can easily do the same thing without copying, via 
prototypes:
https://github.com/rauschma/proto-js

On Nov 13, 2011, at 3:21 , Rick Waldron wrote:

 On Sat, Nov 12, 2011 at 7:08 PM, Brendan Eich bren...@mozilla.com wrote:
 snip
 
 Let's argue about specifics or we'll get nowhere. Do you think Irakli's 
 selfish.js extend (https://github.com/Gozala/selfish/blob/master/selfish.js) 
 is the way to go, or Prototype's quite different form?
 
 Neither of them are fit for standardization. Selfish and Prototype are both 
 incapable of correctly deep copying arrays or objects, resulting in new 
 instances being able to modify values of the base object's properties if 
 those values are elements of an array or property values of an object - 
 because the array and object property themselves are references, not real 
 copies.
 
 PrototypeJS is painfully obvious, Selfish requires a demonstration. I 
 forked/cloned the repo and added a branch with a set of tests:
 
 The branch: https://github.com/rwldrn/selfish/tree/test
 
 The commit: 
 https://github.com/rwldrn/selfish/commit/ee55af5ec00074005fa74e9d9eb4be4dc4db5163
 
 
 An Object.extend() that creates an object full of references is certainly not 
 the way to go.
 
 Rick
 
  
 
 /be
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss
 
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

-- 
Dr. Axel Rauschmayer
a...@rauschma.de

home: rauschma.de
twitter: twitter.com/rauschma
blog: 2ality.com



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


Re: Minimalist (why) classes ?

2011-11-13 Thread Jake Verbaten



 Neither of them are fit for standardization. Selfish and Prototype are
 both incapable of correctly deep copying arrays or objects,


Why does it matter that they don't deep copy? Deep copying is a difficult
problem that needs to be standardized separately. I've personally avoided
deep copying for this reason and don't use it anymore.

One can accept that an extend is merely a shallow copy properties by
reference, because this (although limited) behavior is easy to understand.

I have a version of
Object.extendhttps://github.com/Raynos/pd/blob/master/src/pd.js#L82
that
is a shallow own merge.

However having a deep copy mechanism that works without obscure edge-cases
would be great. Of course it would be nice if we had the choice of deep vs
shallow copy within the API.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Minimalist (why) classes ?

2011-11-13 Thread Axel Rauschmayer
It depends on what kind of `extends` you mean:

- Inheritance: Even though data being kept in prototypes is rare, it’s usually 
better to chain prototypes even when ignoring aliasing problems (no redundant 
properties, instanceof works transitively). Performance degradation should be 
negligible due to internal optimizations.

- Merging objects: Shallow copy is the way to go.

On Nov 13, 2011, at 11:08 , Jake Verbaten wrote:

 
 
 Neither of them are fit for standardization. Selfish and Prototype are both 
 incapable of correctly deep copying arrays or objects,
 
 Why does it matter that they don't deep copy? Deep copying is a difficult 
 problem that needs to be standardized separately. I've personally avoided 
 deep copying for this reason and don't use it anymore.
 
 One can accept that an extend is merely a shallow copy properties by 
 reference, because this (although limited) behavior is easy to understand. 
 
 I have a version of Object.extend that is a shallow own merge.
 
 However having a deep copy mechanism that works without obscure edge-cases 
 would be great. Of course it would be nice if we had the choice of deep vs 
 shallow copy within the API.
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

-- 
Dr. Axel Rauschmayer
a...@rauschma.de

home: rauschma.de
twitter: twitter.com/rauschma
blog: 2ality.com



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


Re: Minimalist (why) classes ?

2011-11-13 Thread Quildreen Motta

On 12/11/11 19:07, John J Barton wrote:

This kind of discussion illustrates my point: JS is not sweet enough
because we are missing core operations for constructing prototypes in
a standard way.
Agreed. I've always thought about JS objects as sets, but it feels weird 
that I don't get disjunction, intersection and other basic operations 
out of the box.


Basically, I've missed primitives for:

- Creating objects that share properties from other objects (Object.create)


- Adding properties to an object (Object.extend)

Object.extend(Object target, Object sources...) → Object
(sources.reduce({|tgt, src|
Object.keys(src).forEach({|key| tgt[key] = src[key]})
tgt }, target)

Should `extend' copy all the properties? Only the own properties? I 
feel `own' properties make more sense.



- Defining new objects that extends on the [[Prototype]], which is 
basically Object.create followed by copying the properties of one or 
more objects over to the new instance. (Object.clone? Object.inherit? I 
never felt `extend' quite says it all)


Object.prototype.clone(Object parent, Object mixins...) → Object
(Object.extend.apply(Object.create(parent), mixins))


- Merging (while possibly flattening, as objects can't have several 
[[Prototype]]s) objects.


Object.merge(Object mixins...) → Object
(x = Object.extend.apply({}, mixins))

Dicts are probably a better answer for this one though.


- Creating instances from objects directly (new Stuff, Stuff.new), 
though I'm not sure there's much sense in having two different standard 
ways of doing the same thing. I guess JS is stuck with constructors =/



- Creating objects by removing/renaming certain properties from other 
objects, which is useful for object composition. Though I guess this 
would be handled by traits(?)



Of course, you still need a better syntax to express it all, and the 
proposed extensions to object literals come close to minimalist classes:


var foo = Base.clone({
method1() { },
method2() { },
get stuff() { }
})

var foo = Base | {
method1() { },
method2() { },
get stuff() { }
}

class foo extends Base {
method1() { }
method2() { }
get stuff() { }
}

That is, if we disregard private and other modifiers. If such modifiers 
were added to the Object literal (meh?), it would be quite the same 
thing. Except a full-blown declarative class syntax could be better 
optimised and would allow for a sugary syntax if/when traits/type guards 
are added.


var foo = Base | {
#constant: 1, // or const
@private_stuff: bar, // or private
method1() { },
method2() { }
get stuff() { }
}

class foo extends Base {
@private_stuff: bar; // or private
#constant: 1; // or const
method1() { }
method2() { }
get stuff() { }
}

Except I'm not sure the @private could be made to work without creating 
confusing semantics around it, so object literals would still be one 
step behind.

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


Re: Minimalist (why) classes ?

2011-11-13 Thread Jake Verbaten

 Should `extend' copy all the properties? Only the own properties? I feel
 `own' properties make more sense.


I agree own makes more sense, we also want to specify whether we want to
extend enumerable properties. Your example does not.



 - Defining new objects that extends on the [[Prototype]], which is
 basically Object.create followed by copying the properties of one or more
 objects over to the new instance. (Object.clone? Object.inherit? I never
 felt `extend' quite says it all)

 Object.prototype.clone(Object parent, Object mixins...) → Object
 (Object.extend.apply(Object.**create(parent), mixins))


I've been referring to this method as
Object.makehttps://github.com/Raynos/pd/blob/master/src/pd.js#L120
it's
defiantly a useful method, however I don't think clone, inherit or
make are correct names for it. clone is probably the most suitable
name, especially if it's on Object.prototype


 var foo = Base | {
 #constant: 1, // or const
 @private_stuff: bar, // or private
 method1() { },
 method2() { }
 get stuff() { }
 }

 Except I'm not sure the @private could be made to work without creating
 confusing semantics around it, so object literals would still be one step
 behind.


As far as I understand @private_stuff would desugar into a name object
only available in scope of the object literal.

var o = {
  @private_stuff: bar;
  method1() { }
}

var o = (function () {
  var private_stuff = name.create();
  var ret = {
method1() { }
  }
  ret[private_stuff] = bar;
})();

I personally don't find that confusing.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Minimalist (why) classes ?

2011-11-13 Thread Axel Rauschmayer
 Except I'm not sure the @private could be made to work without creating 
 confusing semantics around it, so object literals would still be one step 
 behind.
 
 As far as I understand @private_stuff would desugar into a name object only 
 available in scope of the object literal.

The basic idea of private names is that you don't use names directly, but store 
them in a variable and use that variable whenever you need to refer to 
something:

var _name = MyClass_private_a3cfb;
function MyClass(name) {
this[_name] = name;
}

The actual private names are very similar to _name above, but they are not 
strings, they are special objects that are never listed anywhere (one step 
beyond non-enumerable, if you will).

Thus, the challenge is clear: You have to introduce variables such as _name in 
a manner that makes them accessible wherever you need them.

 var o = {
   @private_stuff: bar;
   method1() { }
 }
 
 var o = (function () {
   var private_stuff = name.create();  
   var ret = {
 method1() { }
   }
   ret[private_stuff] = bar;
 })();
 
 I personally don't find that confusing.

The latest ideas are about requiring a private section where you declare 
private_stuff.

var obj = {
private { private_stuff }
@private_stuff: bar,
method1() {
return this.@private_stuff;
}
}

It does desugar like you mention above. If you use constructor functions 
without any tricks, then scope is an issue:

var private_stuff =  name.create(); // it would be nice to have support for a 
private section here
function MyClass(stuff) {
this.@private_stuff = stuff; // same as this[private_stuff]
}
MyClass.prototype.method1 = function () {
return this.@private_stuff; // same as this[private_stuff]
}


-- 
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: Minimalist (why) classes ?

2011-11-13 Thread Rick Waldron


On Nov 13, 2011, at 5:08 AM, Jake Verbaten rayn...@gmail.com wrote:

 
 
 Neither of them are fit for standardization. Selfish and Prototype are both 
 incapable of correctly deep copying arrays or objects,
 
 Why does it matter that they don't deep copy? Deep copying is a difficult 
 problem that needs to be standardized separately.


It matters because I don't want data pollution across instances. It's not a 
hard problem at all, jQuery.extend() has had deep copy for years. 




 I've personally avoided deep copying for this reason and don't use it anymore.
 
 One can accept that an extend is merely a shallow copy properties by 
 reference, because this (although limited) behavior is easy to understand. 
 
 I have a version of Object.extend that is a shallow own merge.
 
 However having a deep copy mechanism that works without obscure edge-cases 
 would be great. Of course it would be nice if we had the choice of deep vs 
 shallow copy within the API.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Function proxies without explicit construct trap

2011-11-13 Thread Tom Van Cutsem
Hi Andreas,

All good points, and I don't recall any of them being intentional. Your
points seem to suggest changing the semantics such that calling new
fproxy() on a function proxy without a construct trap should perhaps just
simply throw a TypeError.

Now, in the direct proxies design, a missing [[Construct]] trap could
simply forward to the [[Construct]] internal method of the target (not the
call trap!). That would be cleaner (direct proxies no longer feature a
virtual prototype, they reuse the target's prototype anyway) and seems to
be where we were trying to take the current [[Construct]] trap default
behavior. Unfortunately, since current proxies don't have a target, we
chose the call trap, which isn't quite the right choice.

Regarding the test case: I think it is broken (IMHO, it expects the most
intuitive result. Since the current semantics don't align with that
intuition, that's a good enough signal for me that we should probably
change the behavior to throw a TypeError). I'll update the test case.

Cheers,
Tom

2011/11/10 Andreas Rossberg rossb...@google.com

 I think the specification of [[Construct]] for function proxies may
 not currently be doing what it is intended to do. If the proxy does
 not have a construct trap, the method simply delegates to the
 [[Construct]] method of the call trap. AFAICS, that has two
 consequences:

 1. The prototype is taken from the call trap, not from the proxy.

 2. If the trap returns a primitive value, that will be ignored and
 replaced with a freshly allocated object, as usual.

 It is not clear to me whether either was intended, but the former
 seems surprising, and the latter is inconsistent with the behaviour
 expected by the construct-primitive test case from
 http://hg.ecmascript.org/tests/harmony/.

 Any ideas?

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

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


Re: Minimalist (why) classes ?

2011-11-13 Thread Rick Waldron
A few more thoughts...

On Nov 13, 2011, at 5:08 AM, Jake Verbaten rayn...@gmail.com wrote:

 
 
 Neither of them are fit for standardization. Selfish and Prototype are both 
 incapable of correctly deep copying arrays or objects,
 
 Why does it matter that they don't deep copy? Deep copying is a difficult 
 problem that needs to be standardized separately. I've personally avoided 
 deep copying for this reason and don't use it anymore.
 
 One can accept that an extend is merely a shallow copy properties by 
 reference, because this (although limited) behavior is easy to understand. 

Shallow copy is only good for one level of property lists whose assignment 
expressions are all primitive, anything that is a reference is going to allow 
the destination to mutate the source, this is wrong. 

 
 I have a version of Object.extend that is a shallow own merge.
 
 However having a deep copy mechanism that works without obscure edge-cases 
 would be great.

Can you be specific? What obscure edge cases have you previously encountered?

 Of course it would be nice if we had the choice of deep vs shallow copy 
 within the API.

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


Re: Minimalist (why) classes ?

2011-11-13 Thread Jake Verbaten

 However having a deep copy mechanism that works without obscure edge-cases
 would be great.


 Can you be specific? What obscure edge cases have you previously
 encountered?



I don't have a list at hand, last time we talked about what it means to
deep copy an arbitary ES-next structure we ran into questions of what it
means to deep copy functions, closures and proxies.

Deep copying data, i.e. anything that can be represented by JSON doesn't
have too many edgecases.

It would actually be nice to have an open lists of unsolved edge cases with
generic deep copying.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Function proxies without explicit construct trap

2011-11-13 Thread Brendan Eich
On Nov 13, 2011, at 7:51 AM, Tom Van Cutsem wrote:

 Hi Andreas,
 
 All good points, and I don't recall any of them being intentional. Your 
 points seem to suggest changing the semantics such that calling new 
 fproxy() on a function proxy without a construct trap should perhaps just 
 simply throw a TypeError.

I recall a bit of intention: we wanted to default to calling the call trap with 
a new object bound to |this|, as is done for user-defined functions.

/be


 
 Now, in the direct proxies design, a missing [[Construct]] trap could simply 
 forward to the [[Construct]] internal method of the target (not the call 
 trap!). That would be cleaner (direct proxies no longer feature a virtual 
 prototype, they reuse the target's prototype anyway) and seems to be where we 
 were trying to take the current [[Construct]] trap default behavior. 
 Unfortunately, since current proxies don't have a target, we chose the call 
 trap, which isn't quite the right choice.
 
 Regarding the test case: I think it is broken (IMHO, it expects the most 
 intuitive result. Since the current semantics don't align with that 
 intuition, that's a good enough signal for me that we should probably change 
 the behavior to throw a TypeError). I'll update the test case.
 
 Cheers,
 Tom
 
 2011/11/10 Andreas Rossberg rossb...@google.com
 I think the specification of [[Construct]] for function proxies may
 not currently be doing what it is intended to do. If the proxy does
 not have a construct trap, the method simply delegates to the
 [[Construct]] method of the call trap. AFAICS, that has two
 consequences:
 
 1. The prototype is taken from the call trap, not from the proxy.
 
 2. If the trap returns a primitive value, that will be ignored and
 replaced with a freshly allocated object, as usual.
 
 It is not clear to me whether either was intended, but the former
 seems surprising, and the latter is inconsistent with the behaviour
 expected by the construct-primitive test case from
 http://hg.ecmascript.org/tests/harmony/.
 
 Any ideas?
 
 /Andreas
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss
 
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

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


Re: [Proxies] Refactoring prototype climbing in the spec

2011-11-13 Thread Tom Van Cutsem
2011/11/10 Allen Wirfs-Brock al...@wirfs-brock.com


 On Nov 10, 2011, at 9:03 AM, Tom Van Cutsem wrote:

 Regarding property deletion: if an object is implemented as a proxy, and
 you would want to delete a property from that object, I'm not sure why you
 would want to circumvent triggering the delete trap?


 In
 http://wiki.ecmascript.org/doku.php?id=strawman:object_model_reformation I'm
 exploring explicitly distinguishing the semants of obj.propName and
 obj[expression] such that an object can explicitly define its
 obj[expression] behaviors without using a Proxy (note that currently  by
 the time a Proxy is called, the distinction is already lost so even if you
 wanted to use a Proxy for this purpose they may not be adequate).  In many
 cases (including the default), the object-specific  handler for
 obj[expression] will delegate back to Object.getProperty/Object.setProperty
 (either directly or via a super call).  But note that it can do so via
 direct [ ] syntax, as that would loop.  This can actually all be modeled
 with a new Reference variant within the spec. that distinguishes .
 references from [ ] references.

 However, I also need to account for the delete operator and distinguish
 delete obj.propName from delete obj[expression] .  This can be taken care
 of by the same reference extension (essentially References needs a delete
 method).  A handler for deleting obj[expression]] may also want to
 delegate back to normal property deletion and for the same reason as for
  obj[exper]  get/set handlers it can't directly use the syntactic form.
  Instead it needs to call an Object.deleteProperty function.


Understood.


 BTW, rather than adding these methods to Object, I'm beginning to think it
 might be better to import them from a built-in reflection module.


Indeed. Perhaps that built-in reflection module could be the same module
that defines the default forwarding handler. Your note that we need an
Object.deleteProperty method apart from the built-in syntax reminded me
that the default forwarding handler for proxies is really all about
providing method-based alternatives to things that can currently only be
achieved through built-in syntax.

In the direct proxies proposal, I proposed defining a Proxy.forward object
that enables forwarding all operations interceptable by proxies to another
object. A prototype implementation of it exists here:

http://code.google.com/p/es-lab/source/browse/trunk/src/proxies/DirectProxies.js#1250


If you observe closely, you'll note that the default forwarding API is
really the dual of the Proxy API.
Proxies uniformly turn all sorts of operations on objects (whether
triggered through syntax or built-in methods) into trap invocations, for
instance:
Object.getOwnPropertyDescriptor(proxy, name) =
handler.getOwnPropertyDescriptor(name, target)
name in proxy = handler.has(name, target)
etc.

The default forwarding API turns these trap invocations back into the
original operations:
Proxy.forward.getOwnPropertyDescriptor(name, target) =
Object.getOwnPropertyDescriptor(target, name);
Proxy.forward.has(name, target) = name in target
etc.

That's why the forwarding API is crucial for double lifting to work: if a
handler is itself a proxy, then to intercept handler[trapName], we need to
be able to generically forward the operation, which is made possible by
writing Proxy.forward[trapName].

I proposed the name Proxy.forward since that looks very natural when
writing handler code that simply wants to augment the default behavior:

funtion makeChangeLogger(target) {
  return Proxy.for(target, {
set: function(receiver, name, value, target) {
  log('property '+name+' on '+target+' set to '+value);
  return Proxy.forward.set(receiver, name, value, target);
}
  });}

However, it now seems to me that the methods encapsulated by Proxy.forward
can be more generally useful for arbitrary meta-programming, not just for
forwarding in the case of proxies.

I see an opportunity here to kill two birds with one stone: we can
introduce a reflection module (assume it's called Reflect for now) that
contains the Proxy.forward methods. That would:
a) obviate the need for Object.deleteProperty (now named Reflect.delete),
Object.getProperty (Reflect.get) and Object.setProperty (Reflect.set).
b) obviate the need for Proxy.forward (the above code snippet would call
Reflect.set instead, which is even shorter)

The design guideline for this Reflect module would be that the methods it
exposes have _exactly_ the same name + parameter list as the Proxy API trap
names. Not only does this retain consistency, it also enables easy double
lifting (or perhaps other design patterns that want to treat operations on
objects / Proxy traps generically).

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


Re: Minimalist (why) classes ?

2011-11-13 Thread Rick Waldron


On Nov 13, 2011, at 11:03 AM, Jake Verbaten rayn...@gmail.com wrote:

 However having a deep copy mechanism that works without obscure edge-cases 
 would be great.
 
 Can you be specific? What obscure edge cases have you previously encountered?
 
 
 I don't have a list at hand, last time we talked about what it means to deep 
 copy an arbitary ES-next structure we ran into questions of what it means to 
 deep copy functions, closures and proxies.

Can you point me to existing discussion threads? 
 
 Deep copying data, i.e. anything that can be represented by JSON doesn't 
 have too many edgecases.
 
 It would actually be nice to have an open lists of unsolved edge cases with 
 generic deep copying.

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


Re: Minimalist (why) classes ?

2011-11-13 Thread Jake Verbaten
On Sun, Nov 13, 2011 at 4:51 PM, Rick Waldron waldron.r...@gmail.comwrote:



 On Nov 13, 2011, at 11:03 AM, Jake Verbaten rayn...@gmail.com wrote:

 However having a deep copy mechanism that works without obscure edge-cases
 would be great.


 Can you be specific? What obscure edge cases have you previously
 encountered?



 I don't have a list at hand, last time we talked about what it means to
 deep copy an arbitary ES-next structure we ran into questions of what it
 means to deep copy functions, closures and proxies.


 Can you point me to existing discussion threads?


The only thing I can find is
https://mail.mozilla.org/pipermail/es-discuss/2011-October/017337.html

This particular thread talked about | and how to make it work on object
references rather then object literals. Since | returns a new object it
would have to clone the object reference in some correct manner.




 Deep copying data, i.e. anything that can be represented by JSON doesn't
 have too many edgecases.

 It would actually be nice to have an open lists of unsolved edge cases
 with generic deep copying.


 This would definitely be useful.

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


Re: Minimalist (why) classes ?

2011-11-13 Thread Brendan Eich
On Nov 13, 2011, at 9:24 AM, Jake Verbaten wrote:

 On Sun, Nov 13, 2011 at 4:51 PM, Rick Waldron waldron.r...@gmail.com wrote:
 
 
 On Nov 13, 2011, at 11:03 AM, Jake Verbaten rayn...@gmail.com wrote:
 
 However having a deep copy mechanism that works without obscure edge-cases 
 would be great.
 
 Can you be specific? What obscure edge cases have you previously encountered?
 
 
 I don't have a list at hand, last time we talked about what it means to deep 
 copy an arbitary ES-next structure we ran into questions of what it means to 
 deep copy functions, closures and proxies.
 
 Can you point me to existing discussion threads? 
 
 The only thing I can find is 
 https://mail.mozilla.org/pipermail/es-discuss/2011-October/017337.html

Quoting with s/identify/identity/g:

No, generalized object clone is relatively hard.  Some other issues:

It isn't just the [[Class]] internal property.  It is all the other 
representational and behavior invariants implied by [[Class]]
What if the object is a Proxy instance?
How should private name properties be handled.
What if there are identity based internal state relationships within the object.
What if there are identity bases external relationships about the object (eg, 
it's used as a key in a WeakMap)
etc.

In other language clone has generally evolved into a little frame that allows 
application level control of some or all of these decisions. 

I'm not saying that some sort of generalized clone wouldn't be useful.  Just 
that it's not so simple.

Allen


 This particular thread talked about | and how to make it work on object 
 references rather then object literals. Since | returns a new object it 
 would have to clone the object reference in some correct manner.
  
 
 
 Deep copying data, i.e. anything that can be represented by JSON doesn't 
 have too many edgecases.
 
 It would actually be nice to have an open lists of unsolved edge cases with 
 generic deep copying.
 
 This would definitely be useful.

See above!

The hard cases include:

1. Closures.
2. Proxies.
3. Private names.
4. Internal hidden state.
5. Side-table entries mapped to the object's identity.

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


Re: Minimalist (why) classes ?

2011-11-13 Thread Brendan Eich
On Nov 13, 2011, at 9:30 AM, Brendan Eich wrote:

 The hard cases include:
 
 1. Closures.
 2. Proxies.
 3. Private names.
 4. Internal hidden state.
 5. Side-table entries mapped to the object's identity.

In the case of objects implemented by C++ or whatever the host implementation 
language might be, the internal or side-table state may not even be 
representable in JS, even in strings (do not want raw pointers, or machine 
addresses however obfuscated, to leak to an attacker).

/be

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


Re: Standard @iter module unfriendly to collection builders

2011-11-13 Thread Erik Arvidsson
Another thing to consider is whether these functions belong in an iter
module or in a reflect module? I'm leaning towards the letter.
On Nov 12, 2011 12:05 PM, Brendan Eich bren...@mozilla.com wrote:

 On Nov 12, 2011, at 11:26 AM, Allen Wirfs-Brock wrote:

 The Iterators proposal includes the definition (
 http://wiki.ecmascript.org/doku.php?id=harmony:iterators#standard_api )
 of functions that are intended to support various common iteration patterns.

 For example,

   for ((k of keys(x)) { ...}
   for (v of values(x)) { ...}
   for ([k,v] of items(x)) {...}
   for (k of allKeys(x)) { ...}
   for (k of allValues(x)) { ...}
   for (i of allItems(x)) { ...}

 The use of these functions seems to be pretty much an essential part of
 the intended use of the for-of statement.


 The prior question is what, if anything,

   for (x of y) ... // and [x for x of y], etc.

 means.

 Should it throw if there's no @iterator private-named property in y *and*
 y is not a Proxy with an iterate trap? That is our current thinking. It may
 not be reflected well in the wiki.

 The alternative is to iterate over property values of an object denoted y
 that has no unstratified @iterator or stratified handler iterate trap. But
 that is hostile to collections and your [] proposal.

 OTOH I see no problem for collection writers if we make for-of throw on
 untrapped objects. Collection authors would bind @iterator, @elementGet,
 and @elementSet. Life would be grand. Right?

 /be

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


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


Re: Minimalist (why) classes ?

2011-11-13 Thread John J Barton
On Sun, Nov 13, 2011 at 7:42 AM, Rick Waldron waldron.r...@gmail.com wrote:


 On Nov 13, 2011, at 5:08 AM, Jake Verbaten rayn...@gmail.com wrote:



 Neither of them are fit for standardization. Selfish and Prototype are
 both incapable of correctly deep copying arrays or objects,

 Why does it matter that they don't deep copy? Deep copying is a difficult
 problem that needs to be standardized separately.

 It matters because I don't want data pollution across instances. It's not
 a hard problem at all, jQuery.extend() has had deep copy for years.

Just a couple of observations:
  1) There are two different issues here: flatten vs retain
[[Prototype]] links and shallow vs deep copy.
  2) I think the choice should be different for methods and data.

The first order effect of inheritance is to re-use methods; for this
purpose shallow copies and re-use by [[Prototype]] links works well.
However, if you adopt shallow copies or re-use by [[Prototype]] links,
the non-method data is copied by reference, causing write onto derived
objects to write onto ancestor object values. This is only rarely the
desired outcome.

In Gonzala's selfish and in his gist, I believe the implicit
assumption is that developers should adopt a pattern of use: ancestor
class objects will have only function properties. The |initialize|
method will define data properties. In this way the shallow copy and
the use of [[Prototype]] links works for the methods and the data is
chained through calls to ancestor initialize().  I think this is also
implicit in Object.create(): LHS object is expected to be a pile of
methods.

This makes a lot of sense and it meshes well with class-thinking. What
it says is: adopt a different strategy for methods and for data. For
methods, retain the [[Prototype]] links; for data, flatten.  The
first-order effect is the same as old PrototypeJS solution but the
second order effect, data in [[Prototype]] links vs data on the
object, is different.

No, I do not have a concrete proposal. But it seems to me that
Gonzala's gist extend() should attach the data properties to the
instance not the type. It only matters when the inputs have data
properties and in that case you probably don't want them on the
[[Prototype]] linked object.

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


Re: Standard @iter module unfriendly to collection builders

2011-11-13 Thread Brendan Eich
On Nov 13, 2011, at 10:17 AM, Erik Arvidsson wrote:

 Another thing to consider is whether these functions belong in an iter module 
 or in a reflect module? I'm leaning towards the letter.
 

Does it matter, apart from the name?

I'd rather have more and more precisely defined modules than one reflect 
dumping ground. JS has built-in reflection, from day 1, arguably overloaded 
with base-level operations but part of the package deal. We won't be factoring 
all such unstratified reflection out.

The @iter name is short and Python-inspired, it should match for-of loops, 
comprehensions, and generators. It could grow too large, but it wouldn't be 
larger than @reflect.

If we end up with a standard prelude, some of these helpers could be imported 
by it.

/be

 On Nov 12, 2011 12:05 PM, Brendan Eich bren...@mozilla.com wrote:
 On Nov 12, 2011, at 11:26 AM, Allen Wirfs-Brock wrote:
 
 The Iterators proposal includes the definition 
 (http://wiki.ecmascript.org/doku.php?id=harmony:iterators#standard_api ) of 
 functions that are intended to support various common iteration patterns.
 
 For example,   
 
   for ((k of keys(x)) { ...}
   for (v of values(x)) { ...}
   for ([k,v] of items(x)) {...}
   for (k of allKeys(x)) { ...}
   for (k of allValues(x)) { ...}
   for (i of allItems(x)) { ...}
 
 The use of these functions seems to be pretty much an essential part of the 
 intended use of the for-of statement.
 
 The prior question is what, if anything,
 
   for (x of y) ... // and [x for x of y], etc.
 
 means.
 
 Should it throw if there's no @iterator private-named property in y *and* y 
 is not a Proxy with an iterate trap? That is our current thinking. It may not 
 be reflected well in the wiki.
 
 The alternative is to iterate over property values of an object denoted y 
 that has no unstratified @iterator or stratified handler iterate trap. But 
 that is hostile to collections and your [] proposal.
 
 OTOH I see no problem for collection writers if we make for-of throw on 
 untrapped objects. Collection authors would bind @iterator, @elementGet, and 
 @elementSet. Life would be grand. Right?
 
 /be
 
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss
 

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


Re: Minimalist (why) classes ?

2011-11-13 Thread John J Barton
On Sun, Nov 13, 2011 at 9:34 AM, Brendan Eich bren...@mozilla.com wrote:
 On Nov 13, 2011, at 9:30 AM, Brendan Eich wrote:

 The hard cases include:

 1. Closures.
 2. Proxies.
 3. Private names.
 4. Internal hidden state.
 5. Side-table entries mapped to the object's identity.

 In the case of objects implemented by C++ or whatever the host implementation 
 language might be, the internal or side-table state may not even be 
 representable in JS, even in strings (do not want raw pointers, or machine 
 addresses however obfuscated, to leak to an attacker).

I think we are on the wrong path here. I guess we followed: a standard
extend() needs a copy-ish operation; a copyish operation is like
cloning; cloning is hard; OMG.

But let's back up. We are looking for one or a few operations such that:
   var a = op(b,c,d,...);
creates a useful result when we use |a| and we are using existing JS
libraries for guidance. By definition there are no show stoppers here.
We are creating new objects from existing objects using operations
available to JS devs, but in standard and recommended way. The only
two things can stop us from being successful: irreconcilable
differences and inertia.

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


Re: Minimalist (why) classes ?

2011-11-13 Thread John J Barton
On Sun, Nov 13, 2011 at 2:36 AM, Axel Rauschmayer a...@rauschma.de wrote:
 It depends on what kind of `extends` you mean:
 - Inheritance: Even though data being kept in prototypes is rare, it’s
 usually better to chain prototypes even when ignoring aliasing problems (no
 redundant properties, instanceof works transitively). Performance
 degradation should be negligible due to internal optimizations.
 - Merging objects: Shallow copy is the way to go.

Perhaps you mean: 'it depends on the use of the object returned by
|extends()|'. But I don't understand your categories. Mine:

Object-like: you want to use the returned object directly. I think a
dev imagines extend() as a kind of initialization, a merger operation:
   var a = merge(b,c,d);
In this case you do not expect deep copy, you expect shallow,
reference copy. If I change d.color, I expect that a.color is changed.
 Or rather, I would say that a dev would not be surprised at this
behavior.

Class-like: you want to use the returned object indirectly, to create
other objects via Foo.prototype/new Foo or similar operation.  Here we
are operating on two levels. In the abstract level we are combining
objects to define factory; in the concrete level we are creating
objects based on that factory.  The data on the inputs to the abstract
level are -- at most -- relevant as initial values for the concrete
level.   You want something like deep copy.

As I mentioned elsewhere, the Object-like merge can be used (with
care) on collections of methods then applied to Foo.prototype. That's
how we get along now: one operation covers both cases just not always
robustly.

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


Re: Minimalist (why) classes ?

2011-11-13 Thread Irakli Gozalishvili
I think this discussion drifted into slightly diff direction.  
What I intended to say was that today all major frameworks use same patter to 
do subclassing. They all implement different APIs to do the following:

function subclass() {
   // init ….
}
subclass.prototype = Object.create(superclass)
Object.defineProperty(subclass.prototype, 'constructor', { value: subclass })
subclass.prototype.method = function() {  
   //...
}

Object.extend used in my gist is BTW same as backbone's .extend and is just a 
shortcut of the code above:

var subclass = superclass.extend({
   initialize: function() {
  // init ...
   },
   method: function() {
  // ….
   }
})

What I'm asking for is a standard function, no matter weather it's 
`Object.extend` or something else that makes it simple to do subclassing. Also 
lisper in me thinks that `Object.extend` method is better than dedicated class 
syntax cause it keeps language concise. In addition I think that if 
`Object.extend` will turn out to be broken it will be easier (not to say easy) 
to fix (`Object.extend = … `) then fixing `class Foo extends Bar`.
Regards
--
Irakli Gozalishvili
Web: http://www.jeditoolkit.com/
Address: 29 Rue Saint-Georges, 75009 Paris, France (http://goo.gl/maps/3CHu)


On Sunday, 2011-11-13 at 13:21 , Brendan Eich wrote:

 On Nov 13, 2011, at 11:28 AM, John J Barton wrote:
  
  On Sun, Nov 13, 2011 at 9:34 AM, Brendan Eich bren...@mozilla.com 
  (mailto:bren...@mozilla.com) wrote:
   On Nov 13, 2011, at 9:30 AM, Brendan Eich wrote:

The hard cases include:
 
1. Closures.
2. Proxies.
3. Private names.
4. Internal hidden state.
5. Side-table entries mapped to the object's identity.
 


   In the case of objects implemented by C++ or whatever the host 
   implementation language might be, the internal or side-table state may 
   not even be representable in JS, even in strings (do not want raw 
   pointers, or machine addresses however obfuscated, to leak to an 
   attacker).
   
  I think we are on the wrong path here. I guess we followed: a standard
  extend() needs a copy-ish operation; a copyish operation is like
  cloning; cloning is hard; OMG.
   
  
  
 That's not what happened. Some people are happy with shallow copy of 
 properties available to ES5 reflection, or even a for-in loop. Others (Rick?) 
 want deep, at least as an option. Deep could skip any private/internal/etc. 
 properties, for sure. But deep tends to get into trouble because if you don't 
 stay shallow, you run immediately into item 1: Closures. How would those be 
 deeply copied, including their lexical environments?
  
  
  But let's back up. We are looking for one or a few operations such that:
  var a = op(b,c,d,...);
  creates a useful result when we use |a| and we are using existing JS
  libraries for guidance. By definition there are no show stoppers here.
   
  
  
 I agree, other than inability to agree on what to standardize.
  
  
  We are creating new objects from existing objects using operations
  available to JS devs, but in standard and recommended way. The only
  two things can stop us from being successful: irreconcilable
  differences and inertia.
   
  
  
 Ok, but this is all meta-pep-talk. What should the reconcilable standard be?
  
 /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: Minimalist (why) classes ?

2011-11-13 Thread Irakli Gozalishvili


On Friday, 2011-11-11 at 18:38 , Brendan Eich wrote:

 Having written all this, I will repeat that I like your selfish work and the 
 exemplar idea
Thanks, that's really encouraging! 
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: An array destructing specification choice

2011-11-13 Thread Brendan Eich
On Nov 12, 2011, at 4:25 PM, Axel Rauschmayer wrote:

 There is no requirement that ...r consume 1 element,
 
 It consumes 0 elements above.

Sorry, misread your example -- we seem to agree that if there aren't enough 
elements, r gets a fresh empty array.

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


Re: Minimalist (why) classes ?

2011-11-13 Thread Brendan Eich
On Nov 13, 2011, at 9:42 PM, Irakli Gozalishvili wrote:

 I think this discussion drifted into slightly diff direction. 
 What I intended to say was that today all major frameworks use same patter to 
 do subclassing. They all implement different APIs to do the following:
 
 function subclass() {
// init ….
 }
 subclass.prototype = Object.create(superclass)
 Object.defineProperty(subclass.prototype, 'constructor', { value: subclass })
 subclass.prototype.method = function() { 
//...
 }

Yes, this is the heart of the matter. Not freezing, not shallow vs. deep 
property copying (where deep must deal with closures at least).


 Object.extend used in my gist is BTW same as backbone's .extend

Ok, good to know. (Jashkenas, you didn't propose it!)


 and is just a shortcut of the code above:
 
 var subclass = superclass.extend({
initialize: function() {
   // init ...
},
method: function() {
   // ….
}
 })
 
 What I'm asking for is a standard function, no matter weather it's 
 `Object.extend` or something else that makes it simple to do subclassing.

Allen has been trying to make it be a combo of | and .{. Agree there could be 
a method, say Object.subclass (what a concept!).


 Also lisper in me thinks that `Object.extend` method is better than dedicated 
 class syntax cause it keeps language concise.

Sorry, JS isn't LISP.


 In addition I think that if `Object.extend` will turn out to be broken it 
 will be easier (not to say easy) to fix (`Object.extend = … `) then fixing 
 `class Foo extends Bar`.

It would be about as hard either way.

/be

 
 Regards
 --
 Irakli Gozalishvili
 Web: http://www.jeditoolkit.com/
 Address: 29 Rue Saint-Georges, 75009 Paris, France
 
 On Sunday, 2011-11-13 at 13:21 , Brendan Eich wrote:
 
 On Nov 13, 2011, at 11:28 AM, John J Barton wrote:
 
 On Sun, Nov 13, 2011 at 9:34 AM, Brendan Eich bren...@mozilla.com wrote:
 On Nov 13, 2011, at 9:30 AM, Brendan Eich wrote:
 
 The hard cases include:
 
 1. Closures.
 2. Proxies.
 3. Private names.
 4. Internal hidden state.
 5. Side-table entries mapped to the object's identity.
 
 In the case of objects implemented by C++ or whatever the host 
 implementation language might be, the internal or side-table state may not 
 even be representable in JS, even in strings (do not want raw pointers, or 
 machine addresses however obfuscated, to leak to an attacker).
 
 I think we are on the wrong path here. I guess we followed: a standard
 extend() needs a copy-ish operation; a copyish operation is like
 cloning; cloning is hard; OMG.
 
 That's not what happened. Some people are happy with shallow copy of 
 properties available to ES5 reflection, or even a for-in loop. Others 
 (Rick?) want deep, at least as an option. Deep could skip any 
 private/internal/etc. properties, for sure. But deep tends to get into 
 trouble because if you don't stay shallow, you run immediately into item 1: 
 Closures. How would those be deeply copied, including their lexical 
 environments?
 
 
 But let's back up. We are looking for one or a few operations such that:
 var a = op(b,c,d,...);
 creates a useful result when we use |a| and we are using existing JS
 libraries for guidance. By definition there are no show stoppers here.
 
 I agree, other than inability to agree on what to standardize.
 
 
 We are creating new objects from existing objects using operations
 available to JS devs, but in standard and recommended way. The only
 two things can stop us from being successful: irreconcilable
 differences and inertia.
 
 Ok, but this is all meta-pep-talk. What should the reconcilable standard be?
 
 /be
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss
 

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