Minimalist (why) classes ?

Brendan Eich brendan at mozilla.com
Mon Nov 14 14:27:43 PST 2011


On Nov 14, 2011, at 2:07 PM, John J Barton wrote:

> Irakli proposes a function; you are discussing classes. So perhaps
> rather than agreeing with Irakli you are drawing a parallel: you like
> the object created by Irakli's extend() and wish to take that into the
> "class" discussion?

Irakli and I are trying to separate concerns. We don't need to solve them all together. We don't even need to "solve" them all at once, if the composition concern is not unitary and has many solutions (my "hydra-headed" phrase), none of which is exclusive of any others.


> That's all fine. But I am focusing on the function vs (class) syntax
> issue. That is where Irakli's "(why) classes" comes from.

Sort of. Irakli's post to which I was replying tried to get back to prototypal wiring. He does show a method definition too, but it does not work the way  his selfish.js works. Hence (I think, if I'm reading him righ) his desire in the post to which I replied to "get back on track".

The problem is that selfish.js mixes in merging and notably freezing. The last in particular is unnecessary and it doesn't help us make progress. You won't find anyone (probably not even Irakli) arguing to standardize selfish.js as-is, instead of classes.


>> How one composes properties from various source objects is a different issue, not directly addressed by class syntax (yet). It is addressed by http://traitsjs.org/ and you can use an expression in the superclass position in the class head: class D extends Trait.create(...) {...}.
> 
> If we compare a |class| syntax
>   class D extends B adds P;
> to Irakli's extend, we write:
>   var D = B.extend(P);
> If both B and P can be expressions, then the forms are equivalent.

No, expressions do not guarantee equivalence. Equivalence depends on crucial details about the syntax and semantics of P. We need to specify to be sure "the forms are equivalent". With most of the classes proposals, they aren't. No freezing, for one. Issues of mutating [[Prototype]] vs. copyiing (shallow vs. deep) with [[Prototype]] update abound.


> That is, both forms have to come up with an answer for how the B and P
> are used in creating D.

Here you're suggesting we make an API to underly class syntax, *whatever* the common semantics.

That may be a good idea, but we need more details to be sure.

No one has objected to APIs for syntactic sugar in general. But the general desire is not a commandment, and in particular, it can be impossible to constrain the semantics and avoid tarpits.

For example, <| has no API that works exactly the same. An Object.beget(lhs, rhs) would observably differ in the case where rhs was not a literal form that constructs a kind of object, in that lhs <| rhs would be an error for any non-literal rhs. The API would have to copy, and now we are back to shallow vs. deep, and if deep, how to copy closures.

So, not to be a broken record: it's crucial to specify the semantics before abstracting and asserting, or even arguing, that we should or must have APIs for all new syntax.


> In the form
>  class D extends B adds P;
> or
>   var D = B.extend(P);
> the properties on P shadow the properties on B.  But the copy-ish
> issue fall on B and P individually.

Nope, because there's no copy in the class D extend B { <P> } syntax. There is no expression evaluated to compute P as an object, and then reflection on that object to define properties of D's new prototype object. Instead the syntax of P as a class body can be specified entirely without resort to any kind of copy-ish copying.


> In Java/C++ languages B and P are highly constrained. Consequently the
> copy-ish issue we discuss here don't apply.  If want B and P to be
> arbitrary expressions,

That's the "If" I'm pushing back on. I don't necessarily want that as a good in itself (Irakli does). In order to decide if it's wanted, the "it" here needs a spec in the class syntax case. If that spec benefits from the syntax, in ways that are lost with a general expression -- in particular if the general expression form raises hard questions about cloning closures -- then the answer to this "If" is "no".

Irakli's selfish.js does a shallow merge-copy-then-freeze, so it dodges the closure copying issue. But Rick reports unwanted sharing, and I'm pretty sure many people object to the freeze. So what do you want for the copy-ish semantics, if you want the general expression form (that is, the API in addition to or underlying the syntax)?

/be


More information about the es-discuss mailing list