|
View:
New views
16 Messages
—
Rating Filter:
Alert me
|
| < Prev | 1 - 2 - 3 | Next > |
|
|
RE: Operator overloading revisitedBrendan Eich wrote:
> If you're worried that the 'class' keyword will hypnotize > the masses into locking things down overmuch, then you > don't trust the masses very much. They'll mostly avoid > new stuff, and any who get burned by inability to monkey- > patch (which is *not* an unmixed blessing) will retreat, > and probably start a "don't use 'class'" movement. > > This is not 'final' in Java (which pace Mark, I believe > was overused, including in the standard library, but > which also has different enough semantics that I wouldn't > drag it in here as a precedent. We're talking about sugar > for ES3 and ES5 facilities already implemented, or nearly > implemented. Will class inheritance then desugar to classical prototype/constructor assignments? Best regards Mike Wilson _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
|
|
|
RE: Operator overloading revisitedBrendan Eich wrote:
> On Jul 21, 2009, at 6:07 PM, Mike Wilson wrote: > > Will class inheritance then desugar to classical > > prototype/constructor assignments? > > The current class proposal, > > http://wiki.ecmascript.org/doku.php?id=strawman:classes > > has zero inheritance. Ah right, thanks for the pointer. Do you expect it to stay this way, and are there good reasons for not providing inheritance? Best regards Mike _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: Operator overloading revisited> The current class proposal,
> > http://wiki.ecmascript.org/doku.php?id=strawman:classes > > has zero inheritance. I was under the impression that the plan was to develop some form of inheritance model too. The strawman says that there is no inheritance to keep the design simple. Are you sure you're not throwing the baby out with the bathwater here? _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: Operator overloading revisited-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1 On Jul 22, 2009, at 3:10 AM, Christian Plesner Hansen wrote: >> The current class proposal, >> >> http://wiki.ecmascript.org/doku.php?id=strawman:classes >> >> has zero inheritance. > > I was under the impression that the plan was to develop some form of > inheritance model too. The strawman says that there is no inheritance > to keep the design simple. Are you sure you're not throwing the baby > out with the bathwater here? Lots of babies have already been thrown out in this proposal (euphemistically named "Resolved Design Choices"): * private by default favors "high integrity" uses of the language, punishing the common case and current practice * closed-classes ignore both the lessons of Ruby and the way that prototypes are currently extended in, say, JQuery * the word "prototype" doesn't occur in the proposal anywhere, meaning that it's silent on the one existing and useful form of object/ factory-function delegation. My sense of it is that this proposal is driven by a desire to avoid hierarchy-as-composition problems (hositing of methods to high positions in hierarchies, etc.) -- which is a well-founded fear. However, it avoids it not by adding a composition mechanism like traits, but instead seeks to turn classes into factories of objects that can't be augmented to fix the errors of initial designs, can't be easily composed to form new types, and don't fit well with how current JS programmers think about their language. In short, it helps Harmony classes make all of the same mistakes that DOM host objects currently plague developers with. Regards - -- Alex Russell slightlyoff@... alex@... BE03 E88D EABB 2116 CC49 8259 CF78 E242 59C3 9723 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.2 (Darwin) iD8DBQFKZySoz3jiQlnDlyMRAjpeAJ9R0PkZOTVx7dtV05qzF2X0sisbRACgm3ta exbKWvCTD1Y8ZkR4BZMQu8U= =TLUq -----END PGP SIGNATURE----- _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: Operator overloading revisitedOn Wed, Jul 22, 2009 at 3:10 AM, Christian Plesner
Hansen<christian.plesner.hansen@...> wrote: >> The current class proposal, >> >> http://wiki.ecmascript.org/doku.php?id=strawman:classes >> >> has zero inheritance. > > I was under the impression that the plan was to develop some form of > inheritance model too. The strawman says that there is no inheritance > to keep the design simple. Are you sure you're not throwing the baby > out with the bathwater here? I have been taking the thread starting at <https://mail.mozilla.org/pipermail/es-discuss/2009-March/009115.html> together with its references to relevant earlier threads as the strawman of interest. Several people have encouraged me to update the wiki. My apologies for not having done so. The proposal in that latest thread itself does not support inheritance, which seems consistent with the general sense of the committee. However, if we do decide to support inheritance, the earlier thread at <https://mail.mozilla.org/pipermail/es-discuss/2008-August/006941.html> shows how to support single inheritance and linearized multiple inheritance in the same framework. Alex mentions traits. Traits seem like a more structured form of behavior sharing than classical inheritance. Lately Alex and I been reading <http://prog.vub.ac.be/Publications/2009/vub-prog-tr-09-04.pdf>. Later today I will post some initial thoughts on how this could also be supported in within the same general framework. The design of well structured inheritance-like behavior sharing machinery is far from settled. As with data types, the ideal outcome would be for ES6 itself to support well all of these as patterns without building any of them in, so that our users and library authors can try multiple experiments. -- Cheers, --MarkM _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: Operator overloading revisitedOn Jul 22, 2009, at 3:10 AM, Christian Plesner Hansen wrote:
>> The current class proposal, >> >> http://wiki.ecmascript.org/doku.php?id=strawman:classes >> >> has zero inheritance. > > I was under the impression that the plan was to develop some form of > inheritance model too. The strawman says that there is no inheritance > to keep the design simple. Are you sure you're not throwing the baby > out with the bathwater here? Nothing is thrown out by starting simple and then considering our options. We all know many ways (too many!) to support inheritance. Would it help to pick a winner prematurely, compared to giving people sugar for high-integrity factories, which they must write the long way in ES5, or not at all in current JS? /be _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Harmony classes [Was: Operator overloading revisited]On 2009-07-22, at 14:14EDT, Brendan Eich wrote:
> We all know many ways (too many!) to support inheritance. Would it > help to pick a winner prematurely, compared to giving people sugar > for high-integrity factories, which they must write the long way in > ES5, or not at all in current JS? On 2009-07-22, at 10:39EDT, Alex Russell wrote: > In short, it helps Harmony classes make all of the same mistakes > that DOM host objects currently plague developers with. So, depending on your point of view, Harmony classes allow the user to create objects that have both the same integrity, and the same limitations, as native objects. I suppose that's a start. But if they don't even support prototypical inheritance, I'll never be able to use them. Give them prototypical inheritance, and I will probably adopt them for their integrity, using my existing pre-processor to emulate the classes and mixins I really want. My only quibble is whether it is confusing to name something so limited 'class'? On 2009-07-22, at 10:52EDT, Mark S. Miller wrote: > Lately Alex and I been > reading <http://prog.vub.ac.be/Publications/2009/vub-prog- > tr-09-04.pdf>. > Later today I will post some initial thoughts on how this could also > be supported in within the same general framework. Thanks for this pointer. I am just starting to read and it looks intriguing. Traits that also have state might just make me give up my mixins! _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: Harmony classes [Was: Operator overloading revisited]On Wed, Jul 22, 2009 at 11:30 AM, P T Withington<ptw@...> wrote:
> On 2009-07-22, at 10:52EDT, Mark S. Miller wrote: > >> Lately Alex and I been >> reading <http://prog.vub.ac.be/Publications/2009/vub-prog-tr-09-04.pdf>. >> Later today I will post some initial thoughts on how this could also >> be supported in within the same general framework. > > Thanks for this pointer. I am just starting to read and it looks > intriguing. Traits that also have state might just make me give up my > mixins! Given the following helper abstractions: ------------------------ const traitConflict() { throw new Error("trait conflict"); } const conflictDesc = Object.freeze({ get: traitConflict, set: undefined, enumerable: false, configurable: true }); const isSameDesc(desc1, desc2) { ... } const addTrait(self, trait, opt_advice) { const advice = opt_advice || {}; Object.getOwnPropertyNames(trait).forEach(const(k) { const newDesc = Object.getOwnPropertyDescriptor(trait, k); if (k in advice) { const k2 = advice[k]; if (k2) { k = k2; /*String(k2); ? */ } else { return; } } const oldDesc = Object.getOwnPropertyDescriptor(self, k); if (oldDesc) { if (isSameDesc(oldDesc, newDesc)) { // already cool } else { Object.defineProperty(self, k, conflictDesc); } } else { Object.defineProperty(self, k, newDesc); } }); } ------------------------ and using no sugar beyond that defined in the thread starting at <https://mail.mozilla.org/pipermail/es-discuss/2009-March/009115.html>, here is the main example from Tom's paper: ------------------------ class AnimationTrait(self, refreshRate) { const timer = makeTimer(); public start() { timer.everyDo(refreshRate, const() { self.animate(); }); } public stop() { timer.reset(); } } const ParticleTrait(self, radius, moveRate, dx, dy) { const resultTrait = {}; addTrait(resultTrait, CircleTrait(self, radius)); addTrait(resultTrait, AnimationTrait(self, moveRate), { start: 'startMoving', stop: false }); addTrait(resultTrait, object { public animate() { self.move(dx, dy); } }); return Object.freeze(resultTrait); } const ParticleMorph(radius, moveRate, dx, dy) { var self = {}; addTrait(self, ParticleTrait(self, radius, moveRate, dx, dy)); return Object.freeze(self); } ------------------------ Once we know whether or not we want to adopt traits, and whether we wish to adopt precisely Tom's traits semantics, we could consider further sugar for supporting exactly this pattern. Until then, and in order to get to such a state of clarity, it is pleasing that traits semantics such as Tom's can be expressed well directly in terms of the currently proposed non-inheriting classes-as-sugar system. -- Cheers, --MarkM _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: Harmony classes [Was: Operator overloading revisited]> const ParticleMorph(radius, moveRate, dx, dy) {
> var self = {}; > addTrait(self, ParticleTrait(self, radius, moveRate, dx, dy)); > return Object.freeze(self); > } Given the additional helper const complete(MakeTrait) { return const MakeObject(...rest) { var self = {}; addTrait(self, MakeTrait(self, ...rest)); return Object.freeze(self); } } we can define ParticleMorph as simply const ParticleMorph = complete(ParticleTrait); -- Text by me above is hereby placed in the public domain Cheers, --MarkM _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
RE: Operator overloading revisited[Still staying in this thread although bad match to subject line, as
I'd like to continue on the discussion of open vs closed classes] Brendan Eich wrote: > > On Jul 22, 2009, at 3:10 AM, Christian Plesner Hansen wrote: > > >> The current class proposal, > >> > >> http://wiki.ecmascript.org/doku.php?id=strawman:classes > >> > >> has zero inheritance. > > > > I was under the impression that the plan was to develop some form of > > inheritance model too. The strawman says that there is no > inheritance > > to keep the design simple. Are you sure you're not > throwing the baby > > out with the bathwater here? > > Nothing is thrown out by starting simple and then considering our > options. I agree a lot with Alex about wanting the ability to create non- frozen classes with the new class mechanism (with respect for not having the whole picture as you in the committee have). Once the new class mechanism was deployed I was hoping to be able to use it for any class-oriented problem, and not having to fall back on old-style prototypes/constructors for certain kinds of classes. With the current (small) feature list of classes I guess it's hard to provide any hard arguments against keeping old-style constructors for open classes, and it *is* elegant to keep the purpose of existing language mechanisms. Though, to me it looks like there is a risk that this design will not fit so well when later expanding the feature list with f ex inheritance or class introspection, and that will leave open classes in the back-water and developers facing questions like: - Ah, you want to use the new non-clunky inheritance mechanism that doesn't force you to actually set up the inheritance through a constructor call to the superclass? Sorry, only available in frozen classes. - Or, you want the new inheritance mechanism that chains constructor calls at instance creation? Only available in frozen classes. - Or, you want to introspect the class to see what members instances will get, without creating and introspecting an actual instance? Only in frozen classes. Of course I am only speculating about potential future additions here, but it is easy to fear that the old-style constructors will have a hard time keeping up with a class mechanism that actually has a class declaration to build features upon. Best regards Mike _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: Harmony classes [Was: Operator overloading revisited]> On Wed, Jul 22, 2009 at 11:30 AM, P T Withington<ptw@...> wrote:
>> On 2009-07-22, at 10:52EDT, Mark S. Miller wrote: >> >>> Lately Alex and I been >>> reading <http://prog.vub.ac.be/Publications/2009/vub-prog-tr-09-04.pdf >>> >. >>> Later today I will post some initial thoughts on how this could also >>> be supported in within the same general framework. >> >> Thanks for this pointer. I am just starting to read and it looks >> intriguing. Traits that also have state might just make me give up >> my >> mixins! I'm very pleased to see that our work is relevant for the Javascript community. If it's any help, the slides I used to present the paper a couple of weeks ago at ECOOP09 are available at: http://prog.vub.ac.be/~tvcutsem/presentations/Traits-ECOOP09.pdf Some comments on Mark's proposal follow: > Given the following helper abstractions: > > ------------------------ > const traitConflict() { > throw new Error("trait conflict"); > } > > const conflictDesc = Object.freeze({ > get: traitConflict, > set: undefined, > enumerable: false, > configurable: true > }); Do I get it right that a trait composition conflict is only raised upon accessing the conflicting property? In AmbientTalk, the error is signaled at composition-time (i.e. as if your addTrait method would raise an exception). What's your rationale for deferring the exception until the property is accessed? > const isSameDesc(desc1, desc2) { ... } > > const addTrait(self, trait, opt_advice) { > const advice = opt_advice || {}; > Object.getOwnPropertyNames(trait).forEach(const(k) { > const newDesc = Object.getOwnPropertyDescriptor(trait, k); > if (k in advice) { > const k2 = advice[k]; > if (k2) { k = k2; /*String(k2); ? */ } else { return; } > } > const oldDesc = Object.getOwnPropertyDescriptor(self, k); > if (oldDesc) { > if (isSameDesc(oldDesc, newDesc)) { > // already cool > } else { > Object.defineProperty(self, k, conflictDesc); > } > } else { > Object.defineProperty(self, k, newDesc); > } > }); > } > ------------------------ If I understand correctly, the line Object.defineProperty(self, k, newDesc); installs the trait's 'newDesc' property in the object denoted by 'self'. Two issues need be taken into account if the property refers to a method: - the trait method needs a way to refer to the composite, such that it can invoke required methods. From your example below I infer that 'self' can be made to refer to the composite because you explicitly parameterize classes with 'self'. This makes sense, especially for traits which can be seen as 'incomplete classes'. - if the trait method refers to lexically free identifiers, will these identifiers be bound correctly if the method is invoked on the composite object? More concretely, using the example below: if the method 'start' is invoked on a ParticleMorph, can I rest assured that the reference to 'timer' in AnimationTrait's 'start' method refers to AnimationTrait's timer? I think it works because you represent methods simply as functions (closures). I assume that newDesc's 'get' propety refers to a function that represents the trait method, and this function has closed over its lexical scope and will correctly refer to lexically free identifiers even when installed in a different object. Am I right? If this is the case, that's great because it avoids the need for Self- style delegation, which we required in our paper because methods were not mere functions (they were implicitly parameterized with 'self', and delegation was required to late-bind 'self' to the composite). > and using no sugar beyond that defined in the thread starting at > <https://mail.mozilla.org/pipermail/es-discuss/2009-March/ > 009115.html>, > here is the main example from Tom's paper: > > ------------------------ > class AnimationTrait(self, refreshRate) { > const timer = makeTimer(); > public start() { > timer.everyDo(refreshRate, const() { self.animate(); }); > } > public stop() { timer.reset(); } > } > > const ParticleTrait(self, radius, moveRate, dx, dy) { > const resultTrait = {}; > addTrait(resultTrait, CircleTrait(self, radius)); > addTrait(resultTrait, AnimationTrait(self, moveRate), { > start: 'startMoving', > stop: false > }); > addTrait(resultTrait, object { > public animate() { self.move(dx, dy); } > }); > return Object.freeze(resultTrait); > } > const ParticleMorph(radius, moveRate, dx, dy) { > var self = {}; > addTrait(self, ParticleTrait(self, radius, moveRate, dx, dy)); > return Object.freeze(self); > } > ------------------------ > > Once we know whether or not we want to adopt traits, and whether we > wish to adopt precisely Tom's traits semantics, we could consider > further sugar for supporting exactly this pattern. Until then, and in > order to get to such a state of clarity, it is pleasing that traits > semantics such as Tom's can be expressed well directly in terms of the > currently proposed non-inheriting classes-as-sugar system. > > > -- > Cheers, > --MarkM _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: Harmony classes [Was: Operator overloading revisited]On Fri, Jul 24, 2009 at 1:08 AM, Tom Van Cutsem<tvcutsem@...> wrote:
>>> On 2009-07-22, at 10:52EDT, Mark S. Miller wrote: >> Given the following helper abstractions: >> >> ------------------------ >> const traitConflict() { >> throw new Error("trait conflict"); >> } >> >> const conflictDesc = Object.freeze({ >> get: traitConflict, >> set: undefined, >> enumerable: false, >> configurable: true >> }); > > Do I get it right that a trait composition conflict is only raised upon > accessing the conflicting property? In AmbientTalk, the error is signaled at > composition-time (i.e. as if your addTrait method would raise an exception). > What's your rationale for deferring the exception until the property is > accessed? This change of semantics was more exploratory than purposeful. A retroactive rationalization though is that a conflict that isn't used shouldn't need resolution. C++ does something like this for its multiple inheritance. Of course, they detect possible use statically as well, so they don't pay the price of delaying the failure till the use actually occurs. If desired, it would be simple to alter the scheme I posted so that it signals the conflict at composition time instead. I have no strong opinion on which we should prefer. >> const isSameDesc(desc1, desc2) { ... } >> >> const addTrait(self, trait, opt_advice) { >> const advice = opt_advice || {}; >> Object.getOwnPropertyNames(trait).forEach(const(k) { >> const newDesc = Object.getOwnPropertyDescriptor(trait, k); >> if (k in advice) { >> const k2 = advice[k]; >> if (k2) { k = k2; /*String(k2); ? */ } else { return; } >> } >> const oldDesc = Object.getOwnPropertyDescriptor(self, k); >> if (oldDesc) { >> if (isSameDesc(oldDesc, newDesc)) { >> // already cool >> } else { >> Object.defineProperty(self, k, conflictDesc); >> } >> } else { >> Object.defineProperty(self, k, newDesc); >> } >> }); >> } >> ------------------------ > > If I understand correctly, the line > > Object.defineProperty(self, k, newDesc); > > installs the trait's 'newDesc' property in the object denoted by 'self'. Yes. > Two > issues need be taken into account if the property refers to a method: > > - the trait method needs a way to refer to the composite, such that it can > invoke required methods. From your example below I infer that 'self' can be > made to refer to the composite because you explicitly parameterize classes > with 'self'. Yes. That's the purpose of the 'self' parameter in that code. > This makes sense, especially for traits which can be seen as > 'incomplete classes'. > > - if the trait method refers to lexically free identifiers, will these > identifiers be bound correctly if the method is invoked on the composite > object? More concretely, using the example below: if the method 'start' is > invoked on a ParticleMorph, can I rest assured that the reference to 'timer' > in AnimationTrait's 'start' method refers to AnimationTrait's timer? Yes. > I think it works because you represent methods simply as functions > (closures). I assume that newDesc's 'get' prope[r]ty refers to a function that > represents the trait method, and this function has closed over its lexical > scope and will correctly refer to lexically free identifiers even when > installed in a different object. Am I right? Yes, except for one detail. In this case, it is newDesc's 'value' property rather than its get property. Starting with ES5, a property is either a "data property" or an "accessor property". The descriptor of a data property has the form { value: <any>, writable: <boolean>, enumerable: <boolean>, configurable: <boolean> } The descriptor of an accessor property has the form { get: <function () -> any>, set: <function (any)>, enumerable: <boolean>, configurable: <boolean> } Reading a data property is equivalent to reading the value of the 'value' property of a descriptor of the data property's current state. Reading an accessor property is equivalent to calling the value of the 'get' property of a descriptor of the accessor property's current state. The start method in the example is a data property, so its descriptor would be of the first form. I used an accessor property in my original post only to represent a conflicted property, so the complaint would happen on any attempt to read the property, whether or not the read was followed by a call. > If this is the case, that's > great because it avoids the need for Self-style delegation, which we > required in our paper because methods were not mere functions (they were > implicitly parameterized with 'self', and delegation was required to > late-bind 'self' to the composite). Yes, exactly. In this pattern, as in your paper, lexical variables are not affected by trait composition. For a property 'foo' exported by a trait, within that trait definition it can be referred to either by lexical variable 'foo' or as 'self.foo'. In the first case, it refers to the 'foo' locally defined by that trait itself. In the second, it refers to whatever 'foo' is finally bound to on the self object resulting from the composition of traits. >> ------------------------ >> class AnimationTrait(self, refreshRate) { >> const timer = makeTimer(); >> public start() { >> timer.everyDo(refreshRate, const() { self.animate(); }); >> } >> public stop() { timer.reset(); } >> } >> >> const ParticleTrait(self, radius, moveRate, dx, dy) { >> const resultTrait = {}; >> addTrait(resultTrait, CircleTrait(self, radius)); >> addTrait(resultTrait, AnimationTrait(self, moveRate), { >> start: 'startMoving', >> stop: false >> }); >> addTrait(resultTrait, object { >> public animate() { self.move(dx, dy); } >> }); >> return Object.freeze(resultTrait); >> } >> const ParticleMorph(radius, moveRate, dx, dy) { >> var self = {}; >> addTrait(self, ParticleTrait(self, radius, moveRate, dx, dy)); >> return Object.freeze(self); >> } >> ------------------------ -- Cheers, --MarkM _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: Harmony classes [Was: Operator overloading revisited]>> Do I get it right that a trait composition conflict is only raised
>> upon >> accessing the conflicting property? In AmbientTalk, the error is >> signaled at >> composition-time (i.e. as if your addTrait method would raise an >> exception). >> What's your rationale for deferring the exception until the >> property is >> accessed? > > This change of semantics was more exploratory than purposeful. A > retroactive rationalization though is that a conflict that isn't used > shouldn't need resolution. C++ does something like this for its > multiple inheritance. Of course, they detect possible use statically > as well, so they don't pay the price of delaying the failure till the > use actually occurs. > > If desired, it would be simple to alter the scheme I posted so that it > signals the conflict at composition time instead. I have no strong > opinion on which we should prefer. Me neither, as long as it's obvious to the programmer what composition caused the conflict. >>> const isSameDesc(desc1, desc2) { ... } >>> >>> const addTrait(self, trait, opt_advice) { >>> const advice = opt_advice || {}; >>> Object.getOwnPropertyNames(trait).forEach(const(k) { >>> const newDesc = Object.getOwnPropertyDescriptor(trait, k); >>> if (k in advice) { >>> const k2 = advice[k]; >>> if (k2) { k = k2; /*String(k2); ? */ } else { return; } >>> } >>> const oldDesc = Object.getOwnPropertyDescriptor(self, k); >>> if (oldDesc) { >>> if (isSameDesc(oldDesc, newDesc)) { >>> // already cool >>> } else { >>> Object.defineProperty(self, k, conflictDesc); >>> } >>> } else { >>> Object.defineProperty(self, k, newDesc); >>> } >>> }); >>> } >>> ------------------------ It's really nice that you can specify trait composition in Javascript using metaprogramming this easily. I checked your implementation against our implementation of traits in AmbientTalk. There is one issue that we had to work around, which relates to "default properties" that are present in every object: we had to exclude such properties 'by default' since they would otherwise always cause conflicts. My guess is that if such properties exist in JS, you would probably set their 'enumerable' field to false to filter them out. >> I think it works because you represent methods simply as functions >> (closures). I assume that newDesc's 'get' prope[r]ty refers to a >> function that >> represents the trait method, and this function has closed over its >> lexical >> scope and will correctly refer to lexically free identifiers even >> when >> installed in a different object. Am I right? > > Yes, except for one detail. In this case, it is newDesc's 'value' > property rather than its get property. Starting with ES5, a property > is either a "data property" or an "accessor property". The descriptor > of a data property has the form > { value: <any>, writable: <boolean>, enumerable: <boolean>, > configurable: <boolean> } > The descriptor of an accessor property has the form > { get: <function () -> any>, set: <function (any)>, enumerable: > <boolean>, configurable: <boolean> } Thanks for the clarification. Could you point me to a page that explains the rationale behind distinguishing data properties from accessor properties? At first sight, it appears you don't need both since accessor properties can easily subsume data properties. Kind regards, Tom _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: Harmony classes [Was: Operator overloading revisited]On Jul 27, 2009, at 2:56 AM, Tom Van Cutsem wrote:
ES5 is a draft standard based on de-facto standards in JavaScript implementations. Accessor properties, commonly called "getters and setters", originated almost ten years ago in Mozilla's SpiderMonkey JS engine. They were reverse-engineered into other engines more recently. JS, originally in Netscape 2 in 1995, and in ECMA-262 editions 1 through 3 (the last edition before ES5, finalized in 1999), had only data properties, with class-wise [[Get]] and [[Put]] meta-methods in the spec but not exposed to programmers. My inspirations for JS back in 1995 included Scheme and Self, neither of which subsumes anything like data properties under accessor properties. What's more, I didn't have time in the early days to support user-defined accessors, although native ones existed under the hood in custom objects defined by the implementation (i.e., "the DOM"). Thus the ES1-3 standards do not describe properties as pairs of accessor functions, or talk about exposing such functions to programmers and allowing custom getters and setters to be defined. Since accessors came later, they are observable. You can tell they're there using the ES5 meta-programming APIs. They differ from data properties in other ways; e.g., you can't shadow an accessor property in a prototype object by assignment. Thus ES5 can't easily or profitably recast all properties as accessor properties. There would still be "data properties" even if the spec formalized on top of accessors. /be _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: Harmony classes [Was: Operator overloading revisited]On Mon, Jul 27, 2009 at 2:56 AM, Tom Van Cutsem<tvcutsem@...> wrote:
>>>> const isSameDesc(desc1, desc2) { ... } >>>> >>>> const addTrait(self, trait, opt_advice) { >>>> [...] >>>> if (oldDesc) { >>>> if (isSameDesc(oldDesc, newDesc)) { >>>> // already cool >>>> } else { >>>> Object.defineProperty(self, k, conflictDesc); >>>> } >>>> } else { >>>> Object.defineProperty(self, k, newDesc); >>>> } >>>> }); >>>> } >>>> ------------------------ > > It's really nice that you can specify trait composition in Javascript using > metaprogramming this easily. I checked your implementation against our > implementation of traits in AmbientTalk. There is one issue that we had to > work around, which relates to "default properties" that are present in every > object: we had to exclude such properties 'by default' since they would > otherwise always cause conflicts. That's why I put the isSameDesc() call into the conditional above. If the same name is bound to the same descriptions into two different traits being composed -- as would happen for example in a diamond composition pattern -- then there's no conflict. > My guess is that if such properties exist > in JS, you would probably set their 'enumerable' field to false to filter > them out. The equivalent of default properties in JS are properties defined on Object.prototype. Until ES5, all object necessarily inherited from Object.prototype, and typically will still. The properties defined by the spec on Object.prototype are indeed defined as non-enumerable. And in ES5, new properties that anyone defines on Object.prototype can (and therefore should) be defined as non-enumerable as well. But none of that is why we avoid a conflict for such methods. Since addTrait() enumerates properties with Object.getOwnPropertyNames(), this enumerates all own properties whether enumerable or not. An "own" property is a property defined directly on the object, as opposed to an "inherited" property. So we avoid the defaults from Object.prototype but we do compose non-enumerable properties. We dodge the false-conflict problem with the isSameDesc() check explained above. -- Cheers, --MarkM _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
| < Prev | 1 - 2 - 3 | Next > |
| Free embeddable forum powered by Nabble | Forum Help |