Class method addition and replacement (was Re: AOP Compatibility)
the moment, but I assume you can't do replace a method on a user class with another ad-hoc function. Absolutely not with fixtures, I was thinking about this, is there any reason why you can't replace a class's method with another method or install a method on an instance object that overrides the class's method, assuming that the method signature remains the same, the body has correct typing use of |this|, and the class is non-final? This seems to have the same integrity as method overriding in subclasses. Being able to do this (and possibly dynamically adding methods to classes) would bring the level of dynamicism that Mark had suggested with his ES4 sugar proposal (being able to create classes on the fly), but without destroying the fundamental ES4 typing/fixture system. This could be used to solve AOP as well, and bring a distinctly higher level of dynamicism which could be leveraged to progressively build, serialize (with proper introspection), and deserialize classes. Essentially, are there mutations to classes and object instances that do not effect integrity and do not violate explicit contracts against mutation (final annotation=no method mutations) that we could allow? Thanks, Kris ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Class method addition and replacement (was Re: AOP Compatibility)
Replacing a method effectively changes the type, even if the signature is the same. If some code creates an instance of a class using new it should be able to rely on it being that type, and make assumptions about how that object will behave. (This is not a matter of breaking polymorphism because the same code created the instance such that there is no possibility of a sub-type instance being present). Allowing methods to be replaced means that other parts of a program could alter the behaviour of an object in a way that could contradict those assumptions. Additionally, allowing methods to be replaced could reduce the effectiveness of early binding optimisations. (Jeff Dyer can correct me if I'm inaccurate here..) In AS3, class methods are referenced via the class's traits table. They may be accessed by name, but calls are bound to addresses where possible, at compile time via the traits. Allowing methods to be overridden would mean a choice of copying the traits for each instance, which would increase memory usage dramatically; or else checking for overrides at runtime for every method call, which would hurt performance. Peter On Thu, Apr 3, 2008 at 4:23 PM, Kris Zyp [EMAIL PROTECTED] wrote: the moment, but I assume you can't do replace a method on a user class with another ad-hoc function. Absolutely not with fixtures, I was thinking about this, is there any reason why you can't replace a class's method with another method or install a method on an instance object that overrides the class's method, assuming that the method signature remains the same, the body has correct typing use of |this|, and the class is non-final? This seems to have the same integrity as method overriding in subclasses. Being able to do this (and possibly dynamically adding methods to classes) would bring the level of dynamicism that Mark had suggested with his ES4 sugar proposal (being able to create classes on the fly), but without destroying the fundamental ES4 typing/fixture system. This could be used to solve AOP as well, and bring a distinctly higher level of dynamicism which could be leveraged to progressively build, serialize (with proper introspection), and deserialize classes. Essentially, are there mutations to classes and object instances that do not effect integrity and do not violate explicit contracts against mutation (final annotation=no method mutations) that we could allow? Thanks, Kris ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Strict mode recap
On Wed, Apr 2, 2008 at 11:15 PM, Lars Hansen [EMAIL PROTECTED] wrote: Is this already in AS3? If so, is it often used? The syntax comes from E4X, which is incorporated into AS3 and Spidermonkey. Try this in Firefox: script type=text/javascript;e4x=1 var x = ns:p xmlns:ns=http://www.opera.com/;ns:qHi there/ns:q/ns:p var ns = new Namespace(http://www.opera.com/;); var em = q document.writeln(x.ns::[em]); /script I'm aware of E4X. I meant: is it possible to refer to lexical bindings in this manner in AS3? I guess I don't see what use case is satisfied by this feature that isn't already met by the existence of Map. After all, the effect of this feature is to turn lexical environments into (quasi) first class maps, with the peculiar restriction that new name/value pairs cannot be added, though existing ones can be mutated. If a user actually needs that functionality, it wouldn't be difficult to subclass Map to get it. And, yes, I know it's already possible to do this with lexically scoped eval. But why do you want to add another way to do it? -Jon ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: Class method addition and replacement (was Re: AOP Compatibility)
Just to echo Peter here, changing a method violates integrity in the worst way. If I say new Cls I *know* that the object I get is of type Cls, and if I know the implementation of that class I know what a call to a method of the type will do. There is no way subclassing can get in the way of that knowledge, but allowing methods to be arbitrarily assigned to (even with constraints on type compatibility) completely destroys that invariant. But that invariant is one of the main benefits of having classes in the first place. (There are efficiency concerns too, but I think the violation of integrity is the important part.) --lars -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Peter Hall Sent: 3. april 2008 09:58 To: Kris Zyp Cc: es4-discuss Discuss Subject: Re: Class method addition and replacement (was Re: AOP Compatibility) Replacing a method effectively changes the type, even if the signature is the same. If some code creates an instance of a class using new it should be able to rely on it being that type, and make assumptions about how that object will behave. (This is not a matter of breaking polymorphism because the same code created the instance such that there is no possibility of a sub-type instance being present). Allowing methods to be replaced means that other parts of a program could alter the behaviour of an object in a way that could contradict those assumptions. Additionally, allowing methods to be replaced could reduce the effectiveness of early binding optimisations. (Jeff Dyer can correct me if I'm inaccurate here..) In AS3, class methods are referenced via the class's traits table. They may be accessed by name, but calls are bound to addresses where possible, at compile time via the traits. Allowing methods to be overridden would mean a choice of copying the traits for each instance, which would increase memory usage dramatically; or else checking for overrides at runtime for every method call, which would hurt performance. Peter On Thu, Apr 3, 2008 at 4:23 PM, Kris Zyp [EMAIL PROTECTED] wrote: the moment, but I assume you can't do replace a method on a user class with another ad-hoc function. Absolutely not with fixtures, I was thinking about this, is there any reason why you can't replace a class's method with another method or install a method on an instance object that overrides the class's method, assuming that the method signature remains the same, the body has correct typing use of |this|, and the class is non-final? This seems to have the same integrity as method overriding in subclasses. Being able to do this (and possibly dynamically adding methods to classes) would bring the level of dynamicism that Mark had suggested with his ES4 sugar proposal (being able to create classes on the fly), but without destroying the fundamental ES4 typing/fixture system. This could be used to solve AOP as well, and bring a distinctly higher level of dynamicism which could be leveraged to progressively build, serialize (with proper introspection), and deserialize classes. Essentially, are there mutations to classes and object instances that do not effect integrity and do not violate explicit contracts against mutation (final annotation=no method mutations) that we could allow? Thanks, Kris ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: Strict mode recap
-Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Jon Zeppieri Sent: 3. april 2008 10:10 To: Lars Hansen Cc: es4-discuss@mozilla.org Subject: Re: Strict mode recap On Wed, Apr 2, 2008 at 11:15 PM, Lars Hansen [EMAIL PROTECTED] wrote: Is this already in AS3? If so, is it often used? The syntax comes from E4X, which is incorporated into AS3 and Spidermonkey. Try this in Firefox: script type=text/javascript;e4x=1 var x = ns:p xmlns:ns=http://www.opera.com/;ns:qHi there/ns:q/ns:p var ns = new Namespace(http://www.opera.com/;); var em = q document.writeln(x.ns::[em]); /script I'm aware of E4X. I meant: is it possible to refer to lexical bindings in this manner in AS3? Yes. AS3 has an annoying restriction on where user-defined namespaces may be used, but the following example captures it without using E4X: package X { namespace myns; class C { myns var v = 37; } var x = myns; var y = v; print((new C).x::[y]); } This does print '37' if compiled with ASC and run through the Tamarin VM. I guess I don't see what use case is satisfied by this feature that isn't already met by the existence of Map. After all, the effect of this feature is to turn lexical environments into (quasi) first class maps, with the peculiar restriction that new name/value pairs cannot be added, though existing ones can be mutated. If a user actually needs that functionality, it wouldn't be difficult to subclass Map to get it. And, yes, I know it's already possible to do this with lexically scoped eval. But why do you want to add another way to do it? Let me turn it around. The syntax ns::v is in the language, for constant identifier v. If E4X is implemented in an implementation (as it will be in ActionScript and presumably in Firefox, at least), so is ns::[expr]. How would a restriction to require ns to be a compile-time constant (in either form) and not a run-time value, or a restriction to disallow the latter form in ES4 but not in E4X, benefit ES4? --lars ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Class method addition and replacement (was Re: AOP Compatibility)
On Apr 3, 2008, at 8:23 AM, Kris Zyp wrote: the moment, but I assume you can't do replace a method on a user class with another ad-hoc function. Absolutely not with fixtures, I was thinking about this, is there any reason why you can't replace a class's method with another method or install a method on an instance object that overrides the class's method, assuming that the method signature remains the same, the body has correct typing use of |this|, and the class is non-final? This seems to have the same integrity as method overriding in subclasses. Being able to do this (and possibly dynamically adding methods to classes) would bring the level of dynamicism that Mark had suggested with his ES4 sugar proposal (being able to create classes on the fly) Mark's sketch did not allow method replacement, however. AOP is not the root password to mutation barriers added to enforce integrity properties. It is not even formally sound, last I looked. And its main use-case is logging or other such post-hoc, cross- cutting instrumentation. If the universe of objects already contains some (like certain built-in objects including DOM nodes in most browsers) whose methods cannot be replaced, which must therefore be wrapped for AOP-style hacking, then why wouldn't we want classes to behave as proposed in ES4? Wrappers will be required; they already are for security in browsers I've studied (or they are coming soon, at any rate). Any code not insisting on a nominal type relation, i.e., using * (implicitly as in untyped code today, or explicitly), or a like test, or a structural subtype test, could let wrappers through. Just as DOM wrappers can satisfy hand-coded shape tests in today's untyped libraries that use AOP. /be ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: Class method addition and replacement (was Re: AOP Compatibility)
Most of the time I would not agree that changing a method is an explicit indication that a developer doesn't want the class to be invariant. Most of the time it's just an indication that I'm (a) hacking to make something (appear to) work or (b) tired and making a mistake. And this goes doubly for team programming and for programs that have a long maintenance life. Classes provide the integrity that is necessary for large systems written by many people over significant periods of time to work; such systems reward commitments to invariants even if those invariants later can become a straightjacket (and require reengineering). In such a system the variation points are (and need to be) explicit. --lars -Original Message- From: Kris Zyp [mailto:[EMAIL PROTECTED] Sent: 3. april 2008 18:02 To: Lars Hansen; Peter Hall Cc: es4-discuss Discuss Subject: Re: Class method addition and replacement (was Re: AOP Compatibility) Just to echo Peter here, changing a method violates integrity in the worst way. If I say new Cls I *know* that the object I get is of type Cls, and if I know the implementation of that class I know what a call to a method of the type will do. There is no way subclassing can get in the way of that knowledge, but allowing methods to be arbitrarily assigned to (even with constraints on type compatibility) completely destroys that invariant. But that invariant is one of the main benefits of having classes in the first place. But if I want the class to behave exactly the same as when I created, why would I change the method? Isn't changing a method an explicit indication that a developer doesn't want the class to be invariant? I believe this is more a philosophical/preferential question. Do you value class integrity/immutably more or dynamicism/mutably? Obviously my preference is towards the latter camp, but perhaps I am in the minority, and the concerns over efficiency are certainly important as well. Thanks, Kris (There are efficiency concerns too, but I think the violation of integrity is the important part.) --lars -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Peter Hall Sent: 3. april 2008 09:58 To: Kris Zyp Cc: es4-discuss Discuss Subject: Re: Class method addition and replacement (was Re: AOP Compatibility) Replacing a method effectively changes the type, even if the signature is the same. If some code creates an instance of a class using new it should be able to rely on it being that type, and make assumptions about how that object will behave. (This is not a matter of breaking polymorphism because the same code created the instance such that there is no possibility of a sub-type instance being present). Allowing methods to be replaced means that other parts of a program could alter the behaviour of an object in a way that could contradict those assumptions. Additionally, allowing methods to be replaced could reduce the effectiveness of early binding optimisations. (Jeff Dyer can correct me if I'm inaccurate here..) In AS3, class methods are referenced via the class's traits table. They may be accessed by name, but calls are bound to addresses where possible, at compile time via the traits. Allowing methods to be overridden would mean a choice of copying the traits for each instance, which would increase memory usage dramatically; or else checking for overrides at runtime for every method call, which would hurt performance. Peter On Thu, Apr 3, 2008 at 4:23 PM, Kris Zyp [EMAIL PROTECTED] wrote: the moment, but I assume you can't do replace a method on a user class with another ad-hoc function. Absolutely not with fixtures, I was thinking about this, is there any reason why you can't replace a class's method with another method or install a method on an instance object that overrides the class's method, assuming that the method signature remains the same, the body has correct typing use of |this|, and the class is non-final? This seems to have the same integrity as method overriding in subclasses. Being able to do this (and possibly dynamically adding methods to classes) would bring the level of dynamicism that Mark had suggested with his ES4 sugar proposal (being able to create classes on the fly), but without destroying the fundamental ES4 typing/fixture system. This could be used to solve AOP as well, and bring a distinctly higher level of dynamicism which could be leveraged to progressively build, serialize (with proper introspection), and deserialize classes. Essentially, are there mutations to classes and object instances that do not effect integrity and do not violate explicit contracts against mutation (final annotation=no
Re: Strict mode recap
On 4/3/08, Lars Hansen [EMAIL PROTECTED] wrote: package X { namespace myns; class C { myns var v = 37; } var x = myns; var y = v; print((new C).x::[y]); } This does print '37' if compiled with ASC and run through the Tamarin VM. This is like the E4X example in one crucial respect: in both cases, you're accessing a property of a first-class object. I'm not arguing against this use of computed names. I don't see any significant difference between the above and: var obj = { x: hello }; print(obj[x]); My claim is simply that... function foo() { var x = hello; } ... here, x is not a property of a first-class object. x's binding environment isn't a datum. But: function foo(name) { ... return null::[name]; } ... treats the environment as if it were a datum. I know that in the ES3 spec all bindings are referred to as properties of objects, but activation objects are only notional entities. The current ES4 proposal seems to raise their status by giving programmers a simple mechanism to (practically) reify them. I guess I don't see what use case is satisfied by this feature that isn't already met by the existence of Map. After all, the effect of this feature is to turn lexical environments into (quasi) first class maps, with the peculiar restriction that new name/value pairs cannot be added, though existing ones can be mutated. If a user actually needs that functionality, it wouldn't be difficult to subclass Map to get it. And, yes, I know it's already possible to do this with lexically scoped eval. But why do you want to add another way to do it? Let me turn it around. The syntax ns::v is in the language, for constant identifier v. If E4X is implemented in an implementation (as it will be in ActionScript and presumably in Firefox, at least), so is ns::[expr]. How would a restriction to require ns to be a compile-time constant (in either form) and not a run-time value, or a restriction to disallow the latter form in ES4 but not in E4X, benefit ES4? From my perspective, it isn't an E4X vs. ES4 distinction; it's a looking up a property of a first-class object vs. using a local variable (or, if you prefer, looking up a property of an activation object) distinction. It's not as if this is an uncommon distinction in programming languages, and the advantage of keeping the distinction is better static analysis, better performance, more tractable code. -Jon --lars ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Strict mode recap
On 04/04/2008, Jon Zeppieri [EMAIL PROTECTED] wrote: This is like the E4X example in one crucial respect: in both cases, you're accessing a property of a first-class object. I'm not arguing against this use of computed names. I don't see any significant difference between the above and: var obj = { x: hello }; print(obj[x]); My claim is simply that... function foo() { var x = hello; } ... here, x is not a property of a first-class object. x's binding environment isn't a datum. But: function foo(name) { ... return null::[name]; } ... treats the environment as if it were a datum. I know that in the ES3 spec all bindings are referred to as properties of objects, but activation objects are only notional entities. The current ES4 proposal seems to raise their status by giving programmers a simple mechanism to (practically) reify them. Except you can't actually make the activation object a first class object. The null namespace (or any other namespace) is orthogonal to the activation object - you can now look up local variables dynamically instead of just statically, but the scope still cannot be leaked out of the function in any way. The only notable change is that you now have a method of making dynamic lookup of the local variables in a scope instead of only static lookup. The method of doing so is considerably better than locally scoped eval because it's restricted to doing just that and nothing more. -- David liorean Andersson ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Strict mode recap
On 4/3/08, liorean [EMAIL PROTECTED] wrote: On 04/04/2008, Jon Zeppieri [EMAIL PROTECTED] wrote: function foo(name) { ... return null::[name]; } ... treats the environment as if it were a datum. I know that in the ES3 spec all bindings are referred to as properties of objects, but activation objects are only notional entities. The current ES4 proposal seems to raise their status by giving programmers a simple mechanism to (practically) reify them. Except you can't actually make the activation object a first class object. The null namespace (or any other namespace) is orthogonal to the activation object - you can now look up local variables dynamically instead of just statically, but the scope still cannot be leaked out of the function in any way. Right, hence the 'practically.' There's no meaningful difference, though; the function simply acts as a proxy for the environment. I mean, what important difference is there (as far as the current discussion is concerned) between: var map = new PeculiarMap([foo, bar, baz]); ... where PeculiarMap is a subclass of Map that maintains a constant set of keys, but allows those keys to be associated with new values, and: var map = (function() { var foo, bar, baz; return { get: function(name) { return null::[name]; }, set: function(name, value) { null::[name] = value; } }; })(); The fact that you can't pass around the activation object itself doesn't seem terribly significant. What would you be able to do if it were a real first-class object that you can't do here? The only notable change is that you now have a method of making dynamic lookup of the local variables in a scope instead of only static lookup. The method of doing so is considerably better than locally scoped eval because it's restricted to doing just that and nothing more. That's fine, but why would you want to do that, at all? My point is this: there's an obvious downside to this kind of lookup (inhibiting static analysis and all that), but there's no obvious upside to it. I suppose the argument goes: if the choice is between calling eval to perform this kind of lookup or using ns::[expr], it's better to use ns::[expr]. I won't argue with that, but it's a false dilemma. You could just use an actual data structure. eval has a real use: runtime code generation. (This does not require dynamically scoped eval, but that's beside the point here.) Dynamic lookup of activation object properties, however, doesn't seem... useful. (I certainly could be wrong about this, but I can't think of a compelling use case. And, again, this does *not* apply to dynamic lookup of first-class object properties, which is obviously useful.) The point being: ES3 programmers who are using eval to perform dynamic lookup of activation object properties don't need a better mechanism to do the same thing, because what they're doing doesn't make sense to begin with. -Jon ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Strict mode recap
On 4/4/08, Jon Zeppieri [EMAIL PROTECTED] wrote: eval has a real use: runtime code generation. (This does not require dynamically scoped eval, but that's beside the point here.) Uh, I meant lexically scoped eval, of course... ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss