An experiment using an object literal based class definition pattern

Axel Rauschmayer axel at rauschma.de
Wed Aug 10 07:28:42 PDT 2011


I find the following points remarkable about Allen’s proposal:
- The <| operator creates prototype chains for both prototypes and constructors. This introduces an important symmetry.
- The merge operator obj.{…} makes object literals usable in many more contexts.

So the consensus is to start with the simplest possible class literal? I don’t think we currently need much more than object literal syntax + sections + subclassing. The only thing that programmers might get wrong is initializing property values in the prototype while thinking that they have created instance properties. But as that is a common pattern for giving default values to instance properties, it shouldn’t cause any problems; instance properties will be created automatically upon *assigning* a value (as opposed to reading it).

In my mind, Allen has shown that such syntactic sugar can be very similar to something you build using only object literals. I find that very important – too much of a gap makes things hard to understand, once you look underneath the surface.

On Aug 9, 2011, at 20:54 , Allen Wirfs-Brock wrote:

> 
> On Aug 9, 2011, at 10:23 AM, Bob Nystrom wrote:
> 
>> 
>> 
>> On Mon, Aug 8, 2011 at 3:14 PM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:
>> ...
>> 
>> I think it's reasonable to ask them to re-organize stuff a bit.
>> 
>> class A {
>> }
>> 
>> class B {
>> }
>> 
>> A.b = new B();
>> B.a = new A();
>> 
>> Do I understand the issue here, or am I missing some pieces?
> 
> It sounds like you got it.
> 
>>  
>> Yes, but by my rule above such a circularity would be an immediate name resolution error.  With class hoisting you have to actually analyze the inheritance chains to detect the error
>> 
>> How does this play with modules? If I have two classes declared in different modules (which I assume will a common case, if not the most common) then hoisting or not hoisting won't help either way will it?
> 
> Dave or Sam probably need to respond.  I haven't yet deeply internalized the semantics for mutually referential  modules in their proposal.  However, in general, I believe that such modules have to be processed as a unit and that would imply some implicit ordering of declarations.
> 
>> 
>> I still think the difference is likely to create confusion and I see no need to follow Java in this choice of keyword.  "subs" or "subclass"  might be a possibility. Or possibly:
>>    class superclass <| subclass () {
>>   }
>> 
> I don't really like that either, but I do think there might be some merit to
>   const subclass = class superclass <| () {/* your class body*/};
> but that's for a different message.
> 
>> It would deeply astonish people to have the base class come before the derived class in a class declaration. I didn't even notice that's what you were doing the first few times I read that. C++, C#, Java, Ruby, Python, Ada, Dylan, CLOS, Eiffel, Objective-C, and Scala are all subclass-first.
>> 
>> Smalltalk and Self are superclass (or parent in the case of Self) first, but that's a syntactic side-effect because subclassing is just a message send and the receiver is on the left. That isn't the case with the syntax we're proposing here, which is a more Algol-style keyword-first form.
>> 
>> 
>> My main concern is baking time for getting more complex syntactic sugar (which, BTW, often ends up being more than just sugar) right.
>> 
>> Baking time is a valid concern, and I think one we all share. The only solution I know of is to get the oven going as soon as we can.
>> 
>> I'm not personally as concerned about classes becoming more than syntactic sugar. JS already has the semantics needed to get something like classes working in a really friendly fashion, so adding new actual semantics would very likely overlap the existing ones in weird and nasty ways. Imagine trying to cram generic functions into Smalltalk while trying to retain the existing single-dispatch behavior too.
> 
> Been there, WRT, multiple inheritance. It wasn't pretty. 
> 
>> You'd end up with a strange chimera at best, and more likely just a stuffed jackalope.
> 
> I think future proofing is also an argument for why we might want to go slow with a comprehensive class declaration syntax.  How confident are we that what we come up with would be suitable for adding multiple inheritance or traits/mix-ins or other plausible future extensions. We haven't even been able to agree on a  declarative property visibility syntax.  If we stop at the level of compositional class definition patterns like I have been proposing we have less risk of painting ourselves into a corner. 
> 
>> 
>> I think that alone will keep us honest. We can't jam in new dispatch semantics without making things really painful for ourselves.
>>  
>> The hoisting issues above are an example of the the sort of complexity that need to be worried about.  Simpler  constructors like <| and .{ are easier to get right and probably have lower long term impact if we get some detail wrong.
>> 
>> Simpler constructs are easier to get right, but I think only because they push the hard work onto our users. If we only give them <| and .{, they'll have to come up with their own patterns to accomplish what they want in terms of those. Those patterns will be just as hard to get right as it would be for us to design a syntax directly in the language. The only difference is that instead of us doing that hard work once (and I'd like to hope we're the best-qualified to do it!), they'll re-invent it over and over again.
> 
> But we shouldn't leave them to come up with their own patterns.  We (I'm now speaking about us more as individuals rather than as TC39) should document and evangelize the recommend compositional pattern for defining "classes" in "ES.next" 
> 
>> 
>> I definitely understand the desire to punt on this, but I think we'd do our users a disservice if we did. I believe we can design a good declarative syntax for this and that if we do so, we'll make ES a language that's easier to read and easier to use.
> 
> Sure, we just have the normal schedule and complexity trade-offs that occur in any significant software project.  I'm not saying that you shouldn't push on this.  I'm more saying that it might not be a disaster if in the end it didn't make the cut, as long as we have the more compositional primitive (<|, super, private names, etc.) that allow synthesis of class-like abstraction patterns. I think it would be a bigger problem to not have those for ES.next.
> 
> Allen
> 

-- 
Dr. Axel Rauschmayer

axel at rauschma.de
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110810/d01e3198/attachment-0001.html>


More information about the es-discuss mailing list