Minimalist (why) classes ?

John J Barton johnjbarton at johnjbarton.com
Mon Nov 14 15:16:17 PST 2011


On Mon, Nov 14, 2011 at 2:27 PM, Brendan Eich <brendan at mozilla.com> wrote:
> 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.

I'm not suggesting such an API. In fact I am suggesting that such an
API is not always possible. If the syntax is
   class D : B { pList }
and requires that B be an identifier and pList list of properties,
then the API would have to have restrictions on the arguments that I
don't think we have a way to express.

>
> 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.

I am not arguing what we should or must have APIs for all new syntax.
I'm not arguing anything about new syntax. You've already decided not
to listen to anyone like me when it comes to new syntax, and I've
already agreed that is a good decision.

The only reason I brought up class syntax was illustrate that class
syntax can force constraints on the inputs to the inheritance that
functions cannot do.

And BTW these constraints may well be the most important advantage of
class syntax. These constraints prevent you from pointing the gun at
yourself.

>
>
>> 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.

Well I did not write
   class D extend B { <P> }
specifically because that would imply that the RHS is a literal. If it
is a literal, then you don't have to copy, which is exactly my point:
the heart of "the problem" is the copy demanded by functions but not
by new syntax.

>
>
>> 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".

Ok that's a fine answer for the new-syntax case. But it does not help
those of us who want functions: we have already decided this question
and the answer has to be 'yes'.

>
> Irakli's selfish.js does a shallow merge-copy-then-freeze, so it dodges the closure copying issue.

Irakli makes one choice, a choice Rick dislikes; and Irakli dislikes
Rick's choice.

>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)?

I want to survey the existing practice and create a set of tests
illustrating the various choices and their trade offs. I don't expect
any choice will satisfy everyone.

jjb


More information about the es-discuss mailing list