Re: es-discuss Digest, Vol 52, Issue 117

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: es-discuss Digest, Vol 52, Issue 117

Axel Rauschmayer
Terminology (created by me, but I think it explains well what is going on):

- |this| points to the object where property lookup starts. It always points to the beginning of the prototype chain.
- |here| points to the object where a property was found. |here| can point to any object in the prototype chain.

|super| starts property lookup in the prototype of |here|, but does not change |this|. That is, a method invoked via |super| still has the same |this| and property lookup via |this| is unchanged. If the super-method again uses |super|, then property lookup will begin in the prototype of |here| (= where the super-method has been found). Etc.

From: Mariusz Nowak <[hidden email]>
Date: June 20, 2011 13:49:20 GMT+02:00
Subject: Re: Making "super" work outside a literal?

It's most sane proposal I think. However few things are not obvious to me,
will following evaluate as I assume:

var A = {
one: function () {
return 'A.foo';
}
};
var B = Object.create(A);

var C = Object.create(B);
C.one = function () {
return super.one();
};

var c1 = Object.create(C);
obj.one(); // 'A.foo'

That would be c1.one(), right?

|here| === C and thus the search for super.one starts in B and finds A.one.

B.two = function () {
this.three();
};
B.three =  function () {
return 'B.three';
};
C.two = function () {
super.two();
};
C.three = function () {
return 'C.three';
};

var c2 = Object.create(C);
c2.two();  // C.three

|here| === C and thus super.two === B.two

B.two() uses the original and unchanged |this| which is still c2.
=> this.three === C.three

SUMMARY: I agree with your findings.




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: es-discuss Digest, Vol 52, Issue 117

Peter Michaux
On Mon, Jun 20, 2011 at 1:27 PM, Axel Rauschmayer <[hidden email]> wrote:

> Terminology (created by me, but I think it explains well what is going on):
> - |this| points to the object where property lookup starts. It always points
> to the beginning of the prototype chain.
> - |here| points to the object where a property was found. |here| can point
> to any object in the prototype chain.
> |super| starts property lookup in the prototype of |here|, but does not
> change |this|. That is, a method invoked via |super| still has the same
> |this| and property lookup via |this| is unchanged. If the super-method
> again uses |super|, then property lookup will begin in the prototype of
> |here| (= where the super-method has been found). Etc.

It doesn't seem quite right that an upward call like

    Object.getPrototypeOf(here).foo.call(this)

has sugar

    super.foo()

but sideways calls like

  here.foo.call(this)

don't have any sugar.

By the way, I like this idea that "super" is available all the time
(not just in an initializer) like "this" is always available; however,
adding another implicit variable "here" which is dynamic like "this"
is disconcerting as "this" has been quite a wild beast in JavaScript
to say the least.

Peter
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Axel Rauschmayer
> It doesn't seem quite right that an upward call like
>
>    Object.getPrototypeOf(here).foo.call(this)
>
> has sugar
>
>    super.foo()
>
> but sideways calls like
>
>  here.foo.call(this)
>
> don't have any sugar.

What is the use case for sideways calls? Can you point me to an example? If you are after data that is private to a given prototype, consider using an IIFE, instead.

There are various interesting ideas in other programming languages when it comes to combining methods while overriding:
- Cooperative methods: force overriding methods to call them.
- Before/after/around methods: are invoked before/after/before+after a method that they override:
http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node285.html

But that would be overkill for ES.next.

> By the way, I like this idea that "super" is available all the time
> (not just in an initializer) like "this" is always available; however,
> adding another implicit variable "here" which is dynamic like "this"
> is disconcerting as "this" has been quite a wild beast in JavaScript
> to say the least.


I framed things in terms of |here|, because that value can be easily produced, as a byproduct of looking for a property. It might also, some day, give us the ability to *set* a property that is not at the beginning of a property chain. For now, programmers would never directly see |here|, only |super|. |super| would be computed on demand, only when someone asks for that value.

--
Dr. Axel Rauschmayer

[hidden email]
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: es-discuss Digest, Vol 52, Issue 117

Brendan Eich-3
In reply to this post by Peter Michaux
On Jun 20, 2011, at 2:51 PM, Peter Michaux wrote:

> By the way, I like this idea that "super" is available all the time
> (not just in an initializer) like "this" is always available; however,
> adding another implicit variable "here" which is dynamic like "this"
> is disconcerting as "this" has been quite a wild beast in JavaScript
> to say the least.

'super' is not dynamic as proposed in http://wiki.ecmascript.org/doku.php?id=harmony:object_initialiser_super. Even in Allen's recent post about Object.defineMethod, 'super' is not bound dynamically per call site, as 'this' is. It's a hidden property of the function object.

/be
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Making "super" work outside a literal?

Axel Rauschmayer
Right. Sorry if I added to the confusion. My explanation was along the lines: “If there is a dynamic |super|, then...”. The lexical |super| is perfectly adequate.

I’d imagine it would work something like this (modulo some syntactic sugar):

var Super = {};
Super.foo = function() {
    return "Super: "+this.id;
};

var Sub = Object.create(Super);
Sub.foo = function me() {
    return "Sub "+me.super.foo.call(this);
};
// The following assignment would normally be made by an inheritance API
Sub.foo.super = Object.getPrototypeOf(Sub);

var s = Object.create(Sub);
s.id = "fcb3";
console.log(s.foo()); // Sub Super: fcb3


On Jun 21, 2011, at 0:43 , Brendan Eich wrote:

> On Jun 20, 2011, at 2:51 PM, Peter Michaux wrote:
>
>> By the way, I like this idea that "super" is available all the time
>> (not just in an initializer) like "this" is always available; however,
>> adding another implicit variable "here" which is dynamic like "this"
>> is disconcerting as "this" has been quite a wild beast in JavaScript
>> to say the least.
>
> 'super' is not dynamic as proposed in http://wiki.ecmascript.org/doku.php?id=harmony:object_initialiser_super. Even in Allen's recent post about Object.defineMethod, 'super' is not bound dynamically per call site, as 'this' is. It's a hidden property of the function object.
>
> /be

--
Dr. Axel Rauschmayer

[hidden email]
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Peter Michaux
In reply to this post by Axel Rauschmayer
On Mon, Jun 20, 2011 at 3:23 PM, Axel Rauschmayer <[hidden email]> wrote:

> What is the use case for sideways calls? Can you point me to an example?

You want to allow the API (a.k.a. public methods) of an object to be
overridden, but you don't want the functionality of any non-overidden
API methods to change. In short, you want to avoid the template
pattern. I gave a synthetic example in the sideways calls thread I
started.


> If you are after data that is private to a given prototype, consider using an IIFE, instead.
>
> There are various interesting ideas in other programming languages when it comes to combining methods while overriding:
> - Cooperative methods: force overriding methods to call them.
> - Before/after/around methods: are invoked before/after/before+after a method that they override:
> http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node285.html
>
> But that would be overkill for ES.next.
>
>> By the way, I like this idea that "super" is available all the time
>> (not just in an initializer) like "this" is always available; however,
>> adding another implicit variable "here" which is dynamic like "this"
>> is disconcerting as "this" has been quite a wild beast in JavaScript
>> to say the least.
>
>
> I framed things in terms of |here|, because that value can be easily produced, as a byproduct of looking for a property. It might also, some day, give us the ability to *set* a property that is not at the beginning of a property chain.

Perhaps useful in combination with __noSuchMethod__. More efficient to
dynamically generate a method on the "here" object once then on all
the "this" inheriting objects one-by-one.

Peter
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: es-discuss Digest, Vol 52, Issue 117

medikoo
In reply to this post by Axel Rauschmayer

rauschma wrote
> var c1 = Object.create(C);
> obj.one(); // 'A.foo'

That would be c1.one(), right?
Yes, sorry edited post twice.

rauschma wrote
|here| === C and thus the search for super.one starts in B and finds A.one.

> B.two = function () {
> this.three();
> };
> B.three =  function () {
> return 'B.three';
> };
> C.two = function () {
> super.two();
> };
> C.three = function () {
> return 'C.three';
> };
>
> var c2 = Object.create(C);
> c2.two();  // C.three

|here| === C and thus super.two === B.two

B.two() uses the original and unchanged |this| which is still c2.
=> this.three === C.three

SUMMARY: I agree with your findings.
From my perspective, this proposal looks perfect. I wouldn't look further :)
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

medikoo
In reply to this post by Peter Michaux

Peter Michaux wrote
On Mon, Jun 20, 2011 at 3:23 PM, Axel Rauschmayer <axel@rauschma.de> wrote:

> What is the use case for sideways calls? Can you point me to an example?

You want to allow the API (a.k.a. public methods) of an object to be
overridden, but you don't want the functionality of any non-overidden
API methods to change. In short, you want to avoid the template
pattern. I gave a synthetic example in the sideways calls thread I
started.
Peter,

I'm actually not sure about that. I would even say that allowing such sideway calls within 'instance' methods would be bad hint. I wouldn't like to approach following code, it doesn't allow to extend A the way I may need to:

var A = function () {};
A.prototype = {
        one: function () {
                return A.prototype.two.call(this, args...);
        },
        two: function () {
                ...
        }
};

If we definitely need to call A.prototype.two whether we extended A or not, then we probably talk about 'static' method which should not be called on instance and should be defined directly on A (or privately within closure), then we may just call it A.two(args...). At least that's what my OOP experience says.

I understand your example at http://old.nabble.com/super%2C-self%2C-and-sideways---durable-vs.-template-p31830714.html to me it's just programmer mistake that should throw error.
Maybe you're looking for some pattern that can be realized using 'static' methods (?) but forcing or introducing such behavior somewhere close 'this' or 'super' logic might not be what people expect. My experience is not that vast, is there any language that provide sugar for such calls ?
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Axel Rauschmayer
In reply to this post by Axel Rauschmayer
From: Mariusz Nowak <[hidden email]>
Date: June 21, 2011 10:54:29 GMT+02:00

From my perspective, this proposal looks perfect. I wouldn't look further :)

I agree. Object literal extensions are all very nice.

Note that (as Brendan mentioned) |here| (which I used to explain things) would be a static value, not a dynamic one (unlike |this|). Or (a static) |super| might just be used directly.




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Peter Michaux
In reply to this post by medikoo
On Tue, Jun 21, 2011 at 1:55 AM, Mariusz Nowak
<[hidden email]> wrote:
> Peter Michaux wrote:

>> You want to allow the API (a.k.a. public methods) of an object to be
>> overridden, but you don't want the functionality of any non-overidden
>> API methods to change. In short, you want to avoid the template
>> pattern. I gave a synthetic example in the sideways calls thread I
>> started.

> I'm actually not sure about that. I would even say that allowing such
> sideway calls within 'instance' methods would be bad hint. I wouldn't like
> to approach following code, it doesn't allow to extend A the way I may need
> to:
>
> var A = function () {};
> A.prototype = {
>        one: function () {
>                return A.prototype.two.call(this, args...);
>        },
>        two: function () {
>                ...
>        }
> };

Yes it may seem inconvenient but it is a decision for the the person
creating the class, not the person trying to extend the class.

Peter
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss