getter and setter inheritance
A question of how inheritance/delegation should work with getters and setters was raised in a recent discussion. If there is an object A whose prototype is object B, and object A defines a getter for property foo, and object B defines a setter for property foo, and we write a value to A.foo, should the setter defined on object B be called? If A didn't define any property on A, the setter would be inherited from B and would be called when A.foo was modified. However, with the getter defined on A, should the inheritance stop at A, because there is a slot defined, or should it continue along the prototype chain because there was no setter defined for that property (nor plain value)? The question also applies when the getter and setter are reversed. When a property is accessed and there is a setter defined, but no getter, should we continue to down the prototype chain to find a getter or a plain value, or stop and return undefined? AFAICT, ES4 doesn't explicitly define which is the correct behavior. Firefox follows the former behavior: B={set foo(v){foo = v}, get bar(){return bar value}} A={get foo(){return foo value}, set bar(v){bar = v}, __proto__:B} A.bar - undefined A.foo = 'new value' - setter is not called, foo is not set Thanks, Kris___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: getter and setter inheritance
2008/5/9 Lars Hansen [EMAIL PROTECTED]: My view is that getters and setters introduce properties and that whatever we do should be appropriate to that model. That is pretty much my view as well. Just a couple of questions that might need addressing, if it hasn't been dealt with already: - Can you have a property together with a getter and/or a setter? - If so: * Is there any way to reach that property from inside the getter/setter without ending up recurring into the getter/setter? * Can a setter modify the property if there is a property but no getter? * Can a getter read the property if there is a property but no setter? Others seem to think that getters and setters introduce a way of invoking normal methods by a different syntax and that they are truly just methods. In the world of classes and instances that may be appropriate, but not in the object-and-property world of ES3, I expect. Or one could consider an ES3 property as a getter/setter pair, if one wished. -- David liorean Andersson ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: getter and setter inheritance
(One bike ride and one cup of coffee later.) Clearly there is a difference between class/interface inheritance on the one hand and prototype inheritance on the other. In either case I think the introduction of a setter and/or a getter in a context introduces definitions for both in that context, essentially a special property that holds a getter/setter pair. A missing getter/setter is generated (that's what ES4 specifies now.) That means that in prototype contexts, if an object has a getter or a setter for a field, the prototype will never be searched for the missing half. In a class context, getters and setters can be overridden because the class instance only has the one special property with the getter/setter pair, and the values in that property depend on the class that the instance is an instance of. So different classes have different pairs. There's no particular problem with interfaces holding getter and setter declarations, they are just constraints on the contents of the implementing class -- the class must have a matching getter or setter definition (possibly inherited from base class). That said, getters and setters in interfaces feels pretty lame, because what they're doing is basically requiring a particular *implementation* of a property. A good interface would require there to be a property x with a particular type, but not worry about whether it was introduced by var, let, const, or implemented as a getter/setter. So, using var to stand for all of those possibilities: interface ArrayLike.T { var length: double; meta function get(n):T; meta function set(n,v:T); } In practice most types implementing ArrayLike would use a getter/setter pair for the length field, but why should the type worry about that? --lars From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Lars Hansen Sent: 9. mai 2008 08:41 To: Kris Zyp; [EMAIL PROTECTED]; es4-discuss Discuss Subject: RE: getter and setter inheritance Very timely questions. I've been worrying about similar things this week (more in the context of the ES4 type system) and not yet reached any conclusions. My view is that getters and setters introduce properties and that whatever we do should be appropriate to that model. Others seem to think that getters and setters introduce a way of invoking normal methods by a different syntax and that they are truly just methods. In the world of classes and instances that may be appropriate, but not in the object-and-property world of ES3, I expect. --lars From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Kris Zyp Sent: 9. mai 2008 07:19 To: [EMAIL PROTECTED]; es4-discuss Discuss Subject: getter and setter inheritance A question of how inheritance/delegation should work with getters and setters was raised in a recent discussion. If there is an object A whose prototype is object B, and object A defines a getter for property foo, and object B defines a setter for property foo, and we write a value to A.foo, should the setter defined on object B be called? If A didn't define any property on A, the setter would be inherited from B and would be called when A.foo was modified. However, with the getter defined on A, should the inheritance stop at A, because there is a slot defined, or should it continue along the prototype chain because there was no setter defined for that property (nor plain value)? The question also applies when the getter and setter are reversed. When a property is accessed and there is a setter defined, but no getter, should we continue to down the prototype chain to find a getter or a plain value, or stop and return undefined? AFAICT, ES4 doesn't explicitly define which is the correct behavior. Firefox follows the former behavior: B={set foo(v){foo = v}, get bar(){return bar value}} A={get foo(){return foo value}, set bar(v){bar = v}, __proto__:B} A.bar - undefined A.foo = 'new value' - setter is not called, foo is not set Thanks, Kris ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Argument matching
What should ES4 do when there are too many or too few arguments? Seems that the RI will apply different behavior depending on whether the function arguments are typed or not. This is not necessarily unexpected. I just want to nail down the rules as the RI and AS3 behave differently in this regard. Consider: function fun(a, b) { print(a); print(b); } Calling this with: fun(1) prints 1 undefined fun(1,2,3,4)prints 1 2 fun(1,undefined) 1 0 both work without error. But if either arg is typed: function fun(a: int, b) { print(a); print(b); } In this case, the following all get TypeErrors fun(1) fun(1, undefined) fun(1,2,3,4) Interestingly, ASC will coerce undefined to 0 if supplied with the correct number of arguments and they are typed as ints. What are the rules for ES4? - If you type formal arguments, it seems the caller must supply the correct number and type of actual parameters - If you don't type the formal arguments, you can supply too few or too many arguments - Should undefined be coerced to 0 if the type is an integer? Michael ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: Argument matching
In strict code (use strict) the number of passed arguments must match the number of expected arguments. This has been agreed upon. I would expect that if too few arguments are passed to a function with a typed interface then you get a type error unless the missing parameter has a type that includes undefined (ie no conversion takes place). Signalling an error because the function has a typed interface is a variant, I guess, but it seems like an orthogonal concern. I would expect excess arguments to typed functions to be ignored silently, as they can be picked up by 'arguments' inside the function. --lars -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Michael O'Brien Sent: 9. mai 2008 10:30 To: es4-discuss Discuss Subject: Argument matching What should ES4 do when there are too many or too few arguments? Seems that the RI will apply different behavior depending on whether the function arguments are typed or not. This is not necessarily unexpected. I just want to nail down the rules as the RI and AS3 behave differently in this regard. Consider: function fun(a, b) { print(a); print(b); } Calling this with: fun(1)prints 1 undefined fun(1,2,3,4) prints 1 2 fun(1,undefined) 1 0 both work without error. But if either arg is typed: function fun(a: int, b) { print(a); print(b); } In this case, the following all get TypeErrors fun(1) fun(1, undefined) fun(1,2,3,4) Interestingly, ASC will coerce undefined to 0 if supplied with the correct number of arguments and they are typed as ints. What are the rules for ES4? - If you type formal arguments, it seems the caller must supply the correct number and type of actual parameters - If you don't type the formal arguments, you can supply too few or too many arguments - Should undefined be coerced to 0 if the type is an integer? Michael ___ 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: Argument matching
Lars Hansen wrote: I would expect excess arguments to typed functions to be ignored silently, as they can be picked up by 'arguments' inside the function. Is there any possibility of making whether a function takes extra arguments part of its type? It seems kind of unfortunate not to be able to report an error when too many args are given, which is a pretty common mistake and usually indicates a bug. Dave ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Argument matching
There is a problem with that. If it is an error to provide too many actual parameters to a function with typed formal parameters, then you either must supply the correct number of args or not type the args. A use case that demonstrates the problem is the Array.some callback. Usually it is supplied with only one argument -- the element. So if a user declares this callback with type annotations, the call will fail as the iterator must supply 3 arguments. So you can't have a callback with just one typed argument for the callback. You must either have one untyped arg or 3 typed arguments. Michael On May 9, 2008, at 10:58 AM, David Mandelin wrote: Lars Hansen wrote: I would expect excess arguments to typed functions to be ignored silently, as they can be picked up by 'arguments' inside the function. Is there any possibility of making whether a function takes extra arguments part of its type? It seems kind of unfortunate not to be able to report an error when too many args are given, which is a pretty common mistake and usually indicates a bug. Dave ___ 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: Argument matching
Comments below: On May 9, 2008, at 10:43 AM, Lars Hansen wrote: In strict code (use strict) the number of passed arguments must match the number of expected arguments. This has been agreed upon. I presume that is at execution time? I would expect that if too few arguments are passed to a function with a typed interface then you get a type error unless the missing parameter has a type that includes undefined (ie no conversion takes place). See comment in following email about Array.some callbacks. Signalling an error because the function has a typed interface is a variant, I guess, but it seems like an orthogonal concern. I would expect excess arguments to typed functions to be ignored silently, as they can be picked up by 'arguments' inside the function. I think this is the only approach that will work for standard mode code. So for Array.some in strict mode, the user must supply 3 typed arguments for the callback. But in standard mode, they can either do that, or supply one untyped arg. I can't think of a better solution (yet). Michael --lars -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Michael O'Brien Sent: 9. mai 2008 10:30 To: es4-discuss Discuss Subject: Argument matching What should ES4 do when there are too many or too few arguments? Seems that the RI will apply different behavior depending on whether the function arguments are typed or not. This is not necessarily unexpected. I just want to nail down the rules as the RI and AS3 behave differently in this regard. Consider: function fun(a, b) { print(a); print(b); } Calling this with: fun(1) prints 1 undefined fun(1,2,3,4) prints 1 2 fun(1,undefined) 1 0 both work without error. But if either arg is typed: function fun(a: int, b) { print(a); print(b); } In this case, the following all get TypeErrors fun(1) fun(1, undefined) fun(1,2,3,4) Interestingly, ASC will coerce undefined to 0 if supplied with the correct number of arguments and they are typed as ints. What are the rules for ES4? - If you type formal arguments, it seems the caller must supply the correct number and type of actual parameters - If you don't type the formal arguments, you can supply too few or too many arguments - Should undefined be coerced to 0 if the type is an integer? Michael ___ 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: Argument matching
The tests below in the RI were in standard mode. So that is an RI bug. Michael On May 9, 2008, at 10:43 AM, Lars Hansen wrote: In strict code (use strict) the number of passed arguments must match the number of expected arguments. This has been agreed upon. I would expect that if too few arguments are passed to a function with a typed interface then you get a type error unless the missing parameter has a type that includes undefined (ie no conversion takes place). Signalling an error because the function has a typed interface is a variant, I guess, but it seems like an orthogonal concern. I would expect excess arguments to typed functions to be ignored silently, as they can be picked up by 'arguments' inside the function. --lars -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Michael O'Brien Sent: 9. mai 2008 10:30 To: es4-discuss Discuss Subject: Argument matching What should ES4 do when there are too many or too few arguments? Seems that the RI will apply different behavior depending on whether the function arguments are typed or not. This is not necessarily unexpected. I just want to nail down the rules as the RI and AS3 behave differently in this regard. Consider: function fun(a, b) { print(a); print(b); } Calling this with: fun(1) prints 1 undefined fun(1,2,3,4) prints 1 2 fun(1,undefined) 1 0 both work without error. But if either arg is typed: function fun(a: int, b) { print(a); print(b); } In this case, the following all get TypeErrors fun(1) fun(1, undefined) fun(1,2,3,4) Interestingly, ASC will coerce undefined to 0 if supplied with the correct number of arguments and they are typed as ints. What are the rules for ES4? - If you type formal arguments, it seems the caller must supply the correct number and type of actual parameters - If you don't type the formal arguments, you can supply too few or too many arguments - Should undefined be coerced to 0 if the type is an integer? Michael ___ 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: Argument matching
There are optional and rest arguments in ES4. Regarding error reporting, strict mode is what gives you sane error checking (generally at run-time). Standard mode is for all you cowboys out there. --lars -Original Message- From: David Mandelin [mailto:[EMAIL PROTECTED] Sent: 9. mai 2008 10:58 To: es4-discuss Discuss Cc: Lars Hansen Subject: Re: Argument matching Lars Hansen wrote: I would expect excess arguments to typed functions to be ignored silently, as they can be picked up by 'arguments' inside the function. Is there any possibility of making whether a function takes extra arguments part of its type? It seems kind of unfortunate not to be able to report an error when too many args are given, which is a pretty common mistake and usually indicates a bug. Dave ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: Argument matching
-Original Message- From: Michael O'Brien [mailto:[EMAIL PROTECTED] Sent: 9. mai 2008 11:09 To: Lars Hansen Cc: es4-discuss Discuss Subject: Re: Argument matching Comments below: On May 9, 2008, at 10:43 AM, Lars Hansen wrote: In strict code (use strict) the number of passed arguments must match the number of expected arguments. This has been agreed upon. I presume that is at execution time? It is. So for Array.some in strict mode, the user must supply 3 typed arguments for the callback. But in standard mode, they can either do that, or supply one untyped arg. static function some(object:!Object, checker:Callable, thisObj:Object=null): boolean { for (let i=0, limit=object.length; i limit ; i++) if (i in object) if (checker.call(thisObj, object[i], i, object)) return true; return false; } The type of 'checker' used to be Checker: type Checker = function (*, double, Object):boolean; but that is painful in practice. The intrinsic instance method still requires a Checker, though. Presumably what you're getting at is that if 'checker' is strict then it must accept three arguments even if we only care about one. This is so. The easiest way to write down a function like that is to use the rest parameter without a parameter name: function f(obj, ...) { /* code here */ } --lars ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: Argument matching
-Original Message- From: Michael O'Brien [mailto:[EMAIL PROTECTED] Sent: 9. mai 2008 11:49 To: Lars Hansen Cc: es4-discuss Discuss Subject: Re: Argument matching Presumably what you're getting at is that if 'checker' is strict then it must accept three arguments even if we only care about one. This is so. The easiest way to write down a function like that is to use the rest parameter without a parameter name: function f(obj, ...) { /* code here */ } Agree, but that may have a performance penalty as the extra args must be converted to an array. Why would they have to be converted to an array, if that array can't be referenced? :) One case where strict mode may be faster than standard ;-) So that I can write up a bug for the RI, my take on the rules is: - In strict mode, the number and types of args must agree. If not, an error is generated. - In standard mode, you can supply too many actual parameters, they will be ignored. If you supply too few, undefined will be automatically supplied for the missing args. In my opinion, yes. But this has not been discussed extensively, and not for a long time, so others may have different understanding. Types must agree in standard mode too, of course (at run-time). --lars The RI exhibits strict behavior in this regard in standard mode. Michael On May 9, 2008, at 11:37 AM, Lars Hansen wrote: -Original Message- From: Michael O'Brien [mailto:[EMAIL PROTECTED] Sent: 9. mai 2008 11:09 To: Lars Hansen Cc: es4-discuss Discuss Subject: Re: Argument matching Comments below: On May 9, 2008, at 10:43 AM, Lars Hansen wrote: In strict code (use strict) the number of passed arguments must match the number of expected arguments. This has been agreed upon. I presume that is at execution time? It is. So for Array.some in strict mode, the user must supply 3 typed arguments for the callback. But in standard mode, they can either do that, or supply one untyped arg. static function some(object:!Object, checker:Callable, thisObj:Object=null): boolean { for (let i=0, limit=object.length; i limit ; i++) if (i in object) if (checker.call(thisObj, object[i], i, object)) return true; return false; } The type of 'checker' used to be Checker: type Checker = function (*, double, Object):boolean; but that is painful in practice. The intrinsic instance method still requires a Checker, though. Presumably what you're getting at is that if 'checker' is strict then it must accept three arguments even if we only care about one. This is so. The easiest way to write down a function like that is to use the rest parameter without a parameter name: function f(obj, ...) { /* code here */ } --lars ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Argument matching
I've only used named rest arguments function f(obj, ...items) I forgot you could do: function f(obj, ...) you're right - no overhead. Another RI bug - that form won't work when you invoke it: **ERROR** MachError: defining out-of-bounds temporary (near a.as: 5:4-5.3) Michael On May 9, 2008, at 12:00 PM, Lars Hansen wrote: -Original Message- From: Michael O'Brien [mailto:[EMAIL PROTECTED] Sent: 9. mai 2008 11:49 To: Lars Hansen Cc: es4-discuss Discuss Subject: Re: Argument matching Presumably what you're getting at is that if 'checker' is strict then it must accept three arguments even if we only care about one. This is so. The easiest way to write down a function like that is to use the rest parameter without a parameter name: function f(obj, ...) { /* code here */ } Agree, but that may have a performance penalty as the extra args must be converted to an array. Why would they have to be converted to an array, if that array can't be referenced? :) One case where strict mode may be faster than standard ;-) So that I can write up a bug for the RI, my take on the rules is: - In strict mode, the number and types of args must agree. If not, an error is generated. - In standard mode, you can supply too many actual parameters, they will be ignored. If you supply too few, undefined will be automatically supplied for the missing args. In my opinion, yes. But this has not been discussed extensively, and not for a long time, so others may have different understanding. Types must agree in standard mode too, of course (at run-time). --lars The RI exhibits strict behavior in this regard in standard mode. Michael On May 9, 2008, at 11:37 AM, Lars Hansen wrote: -Original Message- From: Michael O'Brien [mailto:[EMAIL PROTECTED] Sent: 9. mai 2008 11:09 To: Lars Hansen Cc: es4-discuss Discuss Subject: Re: Argument matching Comments below: On May 9, 2008, at 10:43 AM, Lars Hansen wrote: In strict code (use strict) the number of passed arguments must match the number of expected arguments. This has been agreed upon. I presume that is at execution time? It is. So for Array.some in strict mode, the user must supply 3 typed arguments for the callback. But in standard mode, they can either do that, or supply one untyped arg. static function some(object:!Object, checker:Callable, thisObj:Object=null): boolean { for (let i=0, limit=object.length; i limit ; i++) if (i in object) if (checker.call(thisObj, object[i], i, object)) return true; return false; } The type of 'checker' used to be Checker: type Checker = function (*, double, Object):boolean; but that is painful in practice. The intrinsic instance method still requires a Checker, though. Presumably what you're getting at is that if 'checker' is strict then it must accept three arguments even if we only care about one. This is so. The easiest way to write down a function like that is to use the rest parameter without a parameter name: function f(obj, ...) { /* code here */ } --lars ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss