On Nov 1, 2011, at 11:04 AM, Jeremy Ashkenas wrote:

> I'm afraid that this super() discussion has gotten way off topic from the 
> actual minimalist classes thread (which would be much more fun to talk about)

I agree and it's probably why I may sound slightly grumpy.  Dealing with super 
is not  a problem that we need to open up again.  We have a sound proposal that 
has already been throughly discussed.  This thread seems to be turning into a 
tutorial on the semantics of "super" in OO languages. I'd be happy to engage in 
that in another context but it is something that  we really don't need to do 
here. 


> -- but in the interest of dynamic class bodies, let's run it down.
> 
> On Tue, Nov 1, 2011 at 12:45 PM, Allen Wirfs-Brock <[email protected]> 
> wrote:
> 
> Jeremy, have  you looked at the current super proposal at 
> http://wiki.ecmascript.org/doku.php?id=harmony:object_initialiser_super 
> 
> I hadn't looked at the current super proposal in great depth, but thanks for 
> the link. 
>  
> It does not couple super use with classes at all.  It does make it easy to 
> define a super referencing method in an object or class literal, but the 
> mechanism of super can be applied to any method defined in any object. 
> 
> You are creating confusion by suggesting that the proposed ES6 super support 
> "fails to work at all with regular prototypes".
> 
> Browsing through the examples on the page, the current super proposal *does* 
> seem very coupled to "classes" ... by in this case being coupled to your 
> proposed <| operator.

<| is also not coupled to "classes".  <| is probably best thought of as a 
restricted form of the non-standard __proto__ property.

> If you try to use the proposed super with current standard prototype 
> patterns, this happens:
> 
> Fox.prototype.dig = function() {
>   super.dig();
> };

As described in 
http://wiki.ecmascript.org/doku.php?id=harmony:object_initialiser_super#imperatively_binding_super
 the proper way to do this is:

Object.defineMethod(Fox.prototype, "dig",  function() {
  super.dig();
});

Using the "mustache" operator it could be more concisely expressed as:

Fox.prototype.{dig () {
  super.dig();
};

Use of these forms is necessary for the "plan b" static binding of super. 

We possibly could redefine = to do the necessary rebinding.  It is something 
that I have considered.  However, it would introduces a number of issue.  To 
start it makes every property assignment more expensive because a check must be 
made to see if the RHS evaluates to a function that may require resupering.  It 
also would mean that sometimes property assignment does not preserve identity 
of the RHS value.  Also, there is no way to disguising the cases were a 
property (perhaps array elements) is just being use for data storage of a 
function (perhaps a bound function with a super reference) and the cases where 
a property is actually being used as a method and need to be resupered.  A 
number of these concerns also have backwards compat. issues with existing ES 
code. 


> 
> (new Fox).dig();
> TypeError: Object #<Object> has no method 'dig'
> 
> Likewise, for the other usual way of setting a prototype:
> 
> Fox.prototype = {
>   dig: function() {
>     super.dig();
>   }
> };
> 

This is already problematic because it yields a malformed  prototype object 
whose "constructor" property does not reference Fox.

As shown above .{ would be the property way to express this.  Constructs of the 
form you use here probably should be linted. 

> (new Fox).dig();
> TypeError: Object #<Object> has no method 'dig'



> 
> In the first case, the internal [[Super]] property is null. In the second 
> case, the internal [[Super]] property is Object.prototype. Both cases will be 
> quite frustrating for most JavaScript programmers.
> 
> Naturally, use of the <| operator instead of ".prototype" fixes this, but 
> that coupling of the two syntaxes was the point I was trying to make. There 
> is also Object.defineMethod() ... which would work for setting 
> functions-that-use-super on a prototype imperatively, but that's far too 
> verbose of a solution to propose for the common case. All that I'm trying to 
> say is that the super() that JS.next adopts would do well to continue to work 
> properly in the two examples above.

and that is one of the roles for .{ 

I think what we are seeing here are many of the reasons why designing ES.next 
is not nearly as simple and straightforward as some think it should be.  We 
have a currently primarily exposes a number of composible low level primitives 
for constructing objects.  User desire and we desire to provide higher level 
constructs  for defining abstractions over objects.  Those constructs need to 
be defined in terms of coordinated usage of the existing (and a few new) object 
construction primitive. However, the objects that are created still have to 
behave well when used in combination  with primitively constructed objects that 
don't necessarily maintain the invariants assumed by the new higher-level 
constructs.  In addition, we can't break any existing code and we want to make 
sure that usage of the new features can reasonably be added to existing code.

We don't have a clean slate and viable solultion have to make compromises from 
the ideal. 

> 
>  
> Just saying "I don't think that an efficient, pay-as-you-go dynamic super() 
> will be easy, but with the technical chops of TC39 at your disposal, it 
> should be possible" is not helpful, particular when you make other statement 
> that suggest that you really don't understand all the semantic subtitles of 
> super. I hate to cite "authority" but the semantics and implementation 
> alternatives of super  has been thoroughly explored over 30+ years by 
> object-oriented language designer and implementer including myself.  This is 
> not a new problem, the "technical chops" have already been supplied.  A 
> unique new solution that no one has ever though of before would be welcomed.  
> If you have such a solution, please put it forward.  But don't assume that it 
> is something that has not already been deeperly consider both by TC39 member 
> and other language designers.
> 
> I hear you loud and clear, and would only be too happy to get off your lawn 
> ;) All that I can cite is an utter lack of authority, and little experience 
> with even undergraduate computer science -- there are very few assumptions 
> here on my part. That said, if ES-Discuss wants to be an open forum, 
> sometimes the rabble gets to speak up and be ignorant.

I really welcome your participation, and would particular like to get back to 
talking about "classes".  You certainly belong here. Generally I don't mind 
"tutoring the rabble" (your term, not mine) but in this particularly case it is 
a distraction.


> 
> So, speaking from ignorance, here's a simple proof of concept in ES3 of how 
> dynamic super calls can work with a little bit of metadata:
> 
> https://gist.github.com/1331310
> 
> ... which prints out:
> 
> In the GreatGrandParent.
> In the GrandParent.
> In the Parent.
> In the Child.
> 
> In a more ideal implementation, you'd use references to protos instead of 
> counters, and your metadata would be scoped to be specific to an [object, 
> methodName] pair ... but I think that this example is a bit clearer.
> 
> Hopefully this solution isn't unique or new, but dynamic languages are 
> powerful things, and I would hope that dynamic super() is a pattern that's 
> not logically impossible or inherently inefficient to implement, given a bit 
> of extra bookkeeping behind the scenes.

To quick comments:

1) the problem with super start to occur when you have downward this calls 
(calls from a super accessed method that calls to via this to methods closer to 
the leaf of the prototype hierarchy).  This is where unintended loops can occur 
if you aren't aren't careful in your design.  I don't see your example exercise 
this use case.
2) maintaining state around the inner call is going to have the same sort of 
problem I pointed out about Demitry's proposal.

Allen


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

Reply via email to