More thoughts on Allen’s class definition pattern

# Axel Rauschmayer (12 years ago)

harmony:object_extension_literal_class_pattern

const className = superClass <| function(/*constructor parameters */) {
    //constructor body
    super.constructor(/*arguments to super constructor */);
    this.{
     //per instance property definitions
    };
}.prototype.{
    //instance properties defined on prototype
}.constructor.{
    //class (ie, constructor) properties
};

The main problem is that obj.prototype.{...} does not evaluate to obj, then one could chain additions to the function. With custom Function.prototype.* methods, that can be easily achieved:

const className = superClass <| function(/*constructor parameters */) {
    //constructor body
    super.constructor(/*arguments to super constructor */);
    this.{
     //per instance property definitions
    };
}.proto({
    //instance properties defined on prototype
}).class({
    //class (ie, constructor) properties
});

But what if one could write a function like an object literal?

const className = superClass <| function {
    (/*constructor parameters*/): {
        //constructor body
        super(/*arguments to super constructor*/);
        this.{
            //per instance property definitions
        };
    },
    prototype: {

    }
    //class (ie, constructor) properties    
};
# Jake Verbaten (12 years ago)

Personally I'd ask whether there is a good reason to have "class" properties on the constructor.

//class (ie, constructor) properties

You could have them on the prototype instead and then you can access these class properties through all your instances.

Also you could just re-order the assignment like so :

const className = superClass <| function(/*constructor parameters */) { //constructor body super.constructor(/*arguments to super constructor */); this.{ //per instance property definitions }; }.{ //class (ie, constructor) properties }.prototype.{ //instance properties defined on prototype };

# Axel Rauschmayer (12 years ago)

Personally I'd ask whether there is a good reason to have "class" properties on the constructor.

I’m not too fond of them, either. Many current use cases go away with modules. However, sometimes, you want to define class-specific constants such as Point.ZERO.

Also you could just re-order the assignment like so :

const className = superClass <| function(/*constructor parameters */) { //constructor body super.constructor(/*arguments to super constructor */); this.{ //per instance property definitions }; }.{ //class (ie, constructor) properties }.prototype.{ //instance properties defined on prototype };

Won’t work: The value of className will be the prototype, not the function: x.prototype.{ ... } returns the value of x.prototype after the update.

It might be possible to introduce an operator that returns the value of x after an update. For example (note the missing dot): x.prototype{ ... }

Then the above becomes:

const className = superClass <| function(/*constructor parameters */) { //constructor body super.constructor(/*arguments to super constructor */); this.{ //per instance property definitions }; }.{ //class (ie, constructor) properties }.prototype{ // no dot after "prototype" //instance properties defined on prototype };

# Jake Verbaten (12 years ago)

class-specific constants such as Point.ZERO.

Why can't this be on the prototype? Why do we even pass the constructor function around as an object?

I agree we need a better way of writing this, I think the flaw lies in passing constructor functions around everywhere.

# Axel Rauschmayer (12 years ago)

class-specific constants such as Point.ZERO.

Why can't this be on the prototype? Why do we even pass the constructor function around as an object?

I agree we need a better way of writing this, I think the flaw lies in passing constructor functions around everywhere.

You are preaching to the choir. :-)

Alas, there is no consensus that prototypes are the better exemplar (class, object factory, ...). Some people prefer constructors. Constructor exemplars do have the advantage of being more compatible with existing code. If constructors are here to stay, we need to find a syntax that makes it easy to create them. Class literals and the various class definition patterns are all suitable candidates.

# John J Barton (12 years ago)

On Sat, Oct 29, 2011 at 4:34 PM, Axel Rauschmayer <axel at rauschma.de> wrote:

harmony:object_extension_literal_class_pattern

const className = superClass <| function(/*constructor parameters */) {        //constructor body        super.constructor(/*arguments to super constructor */);        this.{         //per instance property definitions        };    }.prototype.{        //instance properties defined on prototype    }.constructor.{        //class (ie, constructor) properties    };

I totally appreciate Allen's effort to build coherence around the operator-to-be-named-curiously triangle.

For me this form is confusing compared to a class-based language. A() should construct A-s, A.foo() should be a method of A-s. Prototypical classes should have a prototype as their super class.

But here we have a .prototype defining instance properties. I guess every JS dev is puzzled by .prototype already. Compared to a class language, it seems like a hack. Do we really need it?

I'd love to see a riff on Gozala's selfish with the declarative approach. Maybe the gap is too large.

jjb

# Rick Waldron (12 years ago)

On Oct 30, 2011, at 1:03 AM, John J Barton <johnjbarton at johnjbarton.com> wrote:

On Sat, Oct 29, 2011 at 4:34 PM, Axel Rauschmayer <axel at rauschma.de> wrote:

harmony:object_extension_literal_class_pattern

const className = superClass <| function(/*constructor parameters */) { //constructor body super.constructor(/*arguments to super constructor */); this.{ //per instance property definitions }; }.prototype.{ //instance properties defined on prototype }.constructor.{ //class (ie, constructor) properties };

I totally appreciate Allen's effort to build coherence around the operator-to-be-named-curiously triangle.

For me this form is confusing compared to a class-based language. A() should construct A-s, A.foo() should be a method of A-s. Prototypical classes should have a prototype as their super class.

But here we have a .prototype defining instance properties

I see instance properties being defined in their own this.{} block

I guess every JS dev is puzzled by .prototype already. Compared to a class language, it seems like a hack. Do we really need it?

I can't tell if this is sarcasm... Ive long held that prototypes are the next evolutionary step up from classes - developers need to evolve now as well. Perhaps I've misunderstood your meaning?

# Axel Rauschmayer (12 years ago)

I guess every JS dev is puzzled by .prototype already. Compared to a class language, it seems like a hack. Do we really need it?

I can't tell if this is sarcasm... Ive long held that prototypes are the next evolutionary step up from classes - developers need to evolve now as well. Perhaps I've misunderstood your meaning?

I agree with the prototype property of functions being a bit odd. I don’t agree with prototypes being difficult to understand, I find them very elegant (but that doesn’t seem to be what he is saying). I certainly don’t agree that class(-based) languages are easier to understand. It’s the opposite: Always having to create a class to create an object is opposed to how humans think: You don’t start with the abstract, you start with the specific. Self has demonstrated very well that prototype-based inheritance can be very intuitive.

# David Bruant (12 years ago)

Le 30/10/2011 01:34, Axel Rauschmayer a écrit :

harmony:object_extension_literal_class_pattern

const className = superClass <| function(/*constructor parameters */) {
    //constructor body
    super.constructor(/*arguments to super constructor */);
    this.{
     //per instance property definitions
    };
}.prototype.{
    //instance properties defined on prototype
}.constructor.{
    //class (ie, constructor) properties
};

The main problem is that obj.prototype.{...} does not evaluate to obj

I wonder if the "only one semicolon" obsession is really worth it. Consider:

const className = superClass <| function(/*constructor parameters */) { //constructor body super.constructor(/*arguments to super constructor */); this.{ //per instance property definitions }; };

className.prototype.{ // prototype properties };

// and if really necessary: /className.{ // "constructor properties" };/

As far as I'm concern, this is declarative enough:

  1. <| provides the proper "super" (why the ".constructor"?) within the constructor body
  2. <| also sets className.prototype.[[Prototype]] to superClass.prototype
  3. this.{} to initialize instance properties
  4. className.prototype.{} to set prototype properties

Because I write this in 2 instructions (i don't count constructor properties as I don't see why they're needed), I need to repeat "className". A dedicated class syntax would avoid this, I admit.

On a side note. <| also sets className.[[Prototype]] to superClass (5). I still think this is a mistake and that two different operators should be defined. One operator for 1)+2) and the other for 5). 1)+2) is about constructing the proper object when a function is used as a constructor 5) is about setting a custom [[Prototype]] to an object (aka "subclassing"). And as it turns out, functions are objects in JavaScript, hence the ambiguity of the operator. The way I see it, the operator for 1) and 2) would throw if the RHS is not a function expression.

Thoughts on this last point?

# David Bruant (12 years ago)

Le 30/10/2011 11:35, Axel Rauschmayer a écrit :

I certainly don’t agree that class(-based) languages are easier to understand. It’s the opposite: Always having to create a class to create an object is opposed to how humans think: You don’t start with the abstract, you start with the specific. Self has demonstrated very well that prototype-based inheritance can be very intuitive.

I agree. A "singleton" being a design pattern sounds like the weirdest idea in the world to me. If class-based languages had never existed, I wonder if we would be even prounoucing the word "singleton" in the context of object oriented languages.

# Axel Rauschmayer (12 years ago)

I wonder if the "only one semicolon" obsession is really worth it. Consider: [...]

I agree. That’s a point I tried to make earlier: <| plus |super| mostly fix JavaScript inheritance (the shorthand for writing methods in an object literal is nice, too).

As far as I'm concern, this is declarative enough:

  1. <| provides the proper "super" (why the ".constructor"?) within the constructor body

It does make sense: There is a MyClass.prototype.contructor method and you do invoke the constructor as a method. So using super without "constructor" would be syntactic sugar. The syntactic sugar is more necessary if there isn’t ever an explicit "constructor" method. If there is (e.g. with class literals or prototype exemplars), then you don’t need the sugar, because it’s obvious.

  1. <| also sets className.prototype.[[Prototype]] to superClass.prototype
  2. this.{} to initialize instance properties
  3. className.prototype.{} to set prototype properties

Because I write this in 2 instructions (i don't count constructor properties as I don't see why they're needed), I need to repeat "className". A dedicated class syntax would avoid this, I admit.

If you use class literals as a way to create modules, it is also a slight advantage. But ES.next has modules and possibly block lamdbas (as a replacement for IIFEs) that should help.

On a side note. <| also sets className.[[Prototype]] to superClass (5). I still think this is a mistake and that two different operators should be defined. One operator for 1)+2) and the other for 5).

I am fine with how <| works, if you wanted to make a distinction, I would use one operator for setting a prototype and another one for “subclassing”. In subclassing, it makes sense that a “class” inherits the properties of its super-class.

# Axel Rauschmayer (12 years ago)

I guess every JS dev is puzzled by .prototype already. Compared to a class language, it seems like a hack. Do we really need it?

I can't tell if this is sarcasm... Ive long held that prototypes are the next evolutionary step up from classes - developers need to evolve now as well. Perhaps I've misunderstood your meaning?

I agree with the prototype property of functions being a bit odd. I don’t agree with prototypes being difficult to understand, I find them very elegant (but that doesn’t seem to be what he is saying). I certainly don’t agree that class(-based) languages are easier to understand. It’s the opposite: Always having to create a class to create an object is opposed to how humans think: You don’t start with the abstract, you start with the specific. Self has demonstrated very well that prototype-based inheritance can be very intuitive.

Addendum: You should see the assertion at the beginning in context of the last sentence of the email is is quoted from:

I'd love to see a riff on Gozala's selfish with the declarative approach. Maybe the gap is too large.

I agree with that (and this last sentence is a bit at odds with the “class language” comparison).

# Allen Wirfs-Brock (12 years ago)

On Oct 29, 2011, at 4:34 PM, Axel Rauschmayer wrote:

...

But what if one could write a function like an object literal?

const className = superClass <| function {

Over the last couple years we have explored a lot of variations of how to approach this problem. Most of them are captured on the wiki:

strawman:obj_initialiser_constructors, doku.php?id=strawman:obj_initialiser_class_abstraction&rev=1299955398, strawman:obj_initialiser_class_abstraction

(and other intermediate versions of these and other pages)

# Allen Wirfs-Brock (12 years ago)

On Oct 29, 2011, at 5:01 PM, Axel Rauschmayer wrote:

Personally I'd ask whether there is a good reason to have "class" properties on the constructor.

I’m not too fond of them, either. Many current use cases go away with modules. However, sometimes, you want to define class-specific constants such as Point.ZERO.

"class methods" are often used for purposes such as defining secondary factory methods or performing management functions spanning all instances of the class.

It's true that dynamic prototype languages such as self seem to get by fine with only instance methods but they do this by placing behaviors that are not specific to single instances (constant access, factories, etc) on the instances. Class based languages with first-class classes have somewhere else to place such non-instance specific behavior, as methods of the class object. In particular, since "first-class" classes means that classes themselves manifest as objects, they inherently may have methods.

As a prototype inheritance language JavaScript could have followed self-style conventions, but it didn't. In trying to be "Java-like" its core library was organized in a more class like manner including the use of "class methods".

In all languages I have observed, the class methods are used sparingly. A typical class with have one constructor, perhaps several dozen instance methods, and only one or two class methods (many classes have none). Since there are so many fewer class methods than instance methods, it seems acceptable for it to be slightly less convenient to define them then it is to define instance methods.

# John J Barton (12 years ago)

On Sat, Oct 29, 2011 at 10:31 PM, Rick Waldron <waldron.rick at gmail.com> wrote:

On Oct 30, 2011, at 1:03 AM, John J Barton <johnjbarton at johnjbarton.com> wrote:

On Sat, Oct 29, 2011 at 4:34 PM, Axel Rauschmayer <axel at rauschma.de> wrote:

harmony:object_extension_literal_class_pattern

const className = superClass <| function(/*constructor parameters */) {        //constructor body        super.constructor(/*arguments to super constructor */);        this.{         //per instance property definitions        };    }.prototype.{        //instance properties defined on prototype    }.constructor.{        //class (ie, constructor) properties    };

I totally appreciate Allen's effort to build coherence around the operator-to-be-named-curiously triangle.

For me this form is confusing compared to a class-based language.  A() should construct A-s, A.foo() should be a method of A-s. Prototypical classes should have a prototype as their super class.

But here we have a .prototype defining instance properties

I see instance properties being defined in their own this.{} block

I guess every JS dev is puzzled by .prototype already. Compared to a class language, it seems like a hack. Do we really need it?

I can't tell if this is sarcasm...

Not sarcasm. I am asserting that creating instances using a function with special property for methods -- "prototype" -- places JavaScript at a disadvantage. It's a contortion of syntax and vocabulary. Let's not perpetuate this confusion.

Ive long held that prototypes are the next evolutionary step up from classes - developers need to evolve now as well. Perhaps I've misunderstood your meaning?

I guess so, because my point is that the unimportant ".prototype" ('dot prototype') confuses the important 'prototype' in prototypical inheritance.

jjb

# Axel Rauschmayer (12 years ago)

Over the last couple years we have explored a lot of variations of how to approach this problem. Most of them are captured on the wiki:

strawman:obj_initialiser_constructors, doku.php?id=strawman:obj_initialiser_class_abstraction&rev=1299955398, strawman:obj_initialiser_class_abstraction

(and other intermediate versions of these and other pages)

Thanks. Note that my idea is more about defining a callable object using object literal syntax. Conceivably, even the following variation could work:

const className = superClass <| { (arg1, arg2): { //constructor body super(/arguments to super constructor/); this.{ // per instance property definitions }; }, prototype: { // methods } // class (ie, constructor) properties
};

# John J Barton (12 years ago)

On Sun, Oct 30, 2011 at 3:35 AM, Axel Rauschmayer <axel at rauschma.de> wrote:

I guess

every JS dev is puzzled by .prototype already.

Compared to a class

language, it seems like a hack. Do we really need it?

I can't tell if this is sarcasm... Ive long held that prototypes are the next evolutionary step up from classes - developers need to evolve now as well. Perhaps I've misunderstood your meaning?

I agree with the prototype property of functions being a bit odd.

".prototype" (dot prototype) confuses developers. It's way beyond odd.

I don’t agree with prototypes being difficult to understand, I find them very elegant (but that doesn’t seem to be what he is saying). I certainly don’t agree that class(-based) languages are easier to understand. It’s the opposite: Always having to create a class to create an object is opposed to how humans think: You don’t start with the abstract, you start with the specific. Self has demonstrated very well that prototype-based inheritance can be very intuitive.

In the abstract I would agree, but, in our world, every college sophomore CS student learns a class based language and, in our world, prototypical inheritance in JS uses a bizarre pattern of expression. ES should work make this bizarre pattern unnecessary so prototypical inheritance can shine. Using ".prototype" in new patterns heads in the wrong direction: that is the comment I was making on Allen's proposal.

jjb

# Allen Wirfs-Brock (12 years ago)

On Oct 29, 2011, at 10:03 PM, John J Barton wrote:

On Sat, Oct 29, 2011 at 4:34 PM, Axel Rauschmayer <axel at rauschma.de> wrote:

harmony:object_extension_literal_class_pattern

const className = superClass <| function(/*constructor parameters */) { //constructor body super.constructor(/*arguments to super constructor */); this.{ //per instance property definitions }; }.prototype.{ //instance properties defined on prototype }.constructor.{ //class (ie, constructor) properties };

I totally appreciate Allen's effort to build coherence around the operator-to-be-named-curiously triangle.

For me this form is confusing compared to a class-based language. A() should construct A-s, A.foo() should be a method of A-s. Prototypical classes should have a prototype as their super class.

A fundamental difference between prototype languages (for example self) and class-bassed dynamic languages such as Smalltalk and Ruby is that the class-based languages have two, roughly parallel, inheritance hierarchies for each "class". Instances of a class inherit superclass instance behavior while the class objects themselves inherit behavior from the superclass objects. These are independent inheritance chains.

(see chapter 13 of gforge.inria.fr/frs/download.php/25599/PBE1-2009-10-28.pdf ) of an excellent explanation of such parallel hierarchies)

  superClass <| function ...

is also setting up two parallel inheritance chains. the function expression is creating a new "class object" (which in JS we also refer to as a "constructor") which inherits its behavior form the class object (ie, a constructor) superClass. The instance behavior of the new "class" is defined by the the prototype object associated with the new class (instances inherit from the prototype object). The prototype object inherits from the prototype associated with superClass.

But here we have a .prototype defining instance properties. I guess every JS dev is puzzled by .prototype already. Compared to a class language, it seems like a hack. Do we really need it?

this is one of the differences between prototypal and class based languages. In prototypal languages the methods that are shared by all instances of an object abstraction explicitly exist in the "prototype object" and can be directly observed and manipulated at runtime by the programmer.. Class based languages store the shared instance methods in a typically invisible data structure (a "method dictionary"). Usually a reflection API has to be used to view or manipulate the content of this data structure at runtime.

JS is what it is. I don't think it is possible to make prototypes disappear without breaking many (most??) existing JS programs.

I'd love to see a riff on Gozala's selfish with the declarative approach. Maybe the gap is too large.

It has been proposed in many variations.

The basic way that object abstractions are instantiated in the self language is via a copy/initialize sequence. You send a copy message to a Prototype object, typically this creates a new object that inherits form the Prototype and then invokes the initialize method on the new object to set up and instance specific state.

In selfish, the "new" method is the equivalent of self's "copy" method and selfish's "initialize" method serves a similar role to self's "initialize" method. If you have to define a lot of methods (typically because the object you are defining is going to be used as a Prototype), it's inconvenient to do this in the initialize method, so both self and selfish provide a way to directly define a new Prototype object. In self, this is via its IDE and reflection API. In selfish it is via the "extend" method.

The "object exemplar" proposal I have talked about also exactly parallels this same self/selfish model. With object exemplars, the JS new operator corresponds to self's "copy" and selfish's "new" method. With object exemplars the "constructor" method corresponds to the self/selfish "initialize" method.

So where in self you would: Derive a new prototype object named Dog from a prototype named Mammal using the IDE. Create a Dog instance by saying: Dog new: 'Labrador' which creates a new object that inherits from Dog. The "initialize method is invoked on the new instance passing "Labrador" as the argument.

In selfish you would: Derive a new prototype named Dog by evaluating: var Dog = Mammal.extend ({ initialize: function(breed) {this.breed = breed}, /* other dog methods */ }); You would create a Dog instance by saying Dog.new("Labrador") which creates a new object that inherits from Dog. The "initialize" method is invoked on the new instance passing "Labrador" as the argument.

In JS using my object exemplar proposal you would: Derive a new prototype named Dog by evaluating: var Dog = Mammal <| { constructor: function(breed) {this.breed = breed}, /* other dog methods */ }); You would create a Dog instance by saying new Dog("Labrador") which creates a new object that inherits from Dog. The "constructor" method is invoked on the new instance passing "Labrador" as the argument.

The object exemplar approach is just like self or selfish, except that it builds upon features that are already in JS. Specifically, it uses the new operator instead of a new method and it names the initialization method "constructor" in order to tie into the object construction mechanisms that already exist in JS.

# Allen Wirfs-Brock (12 years ago)

On Oct 30, 2011, at 3:36 AM, David Bruant wrote:

... I wonder if the "only one semicolon" obsession is really worth it. Consider:


const className = superClass <| function(/*constructor parameters */) { //constructor body super.constructor(/*arguments to super constructor */); this.{ //per instance property definitions }; };

className.prototype.{ // prototype properties };

// and if really necessary: /className.{ // "constructor properties" };/

As far as I'm concern, this is declarative enough:

  1. <| provides the proper "super" (why the ".constructor"?) within the constructor body

In general, it is necessary to know at runtime what property name you are doing a super look up for. the name can be either implicit or explicit but it has to come from somewhere and generally JS functions don't always have intrinsic names. Also there are some issues relating to super references to getter/setter properties that make the explicit name nice. Also, sometimes the method you want to super invoke is the name same name as the current method (for example, see allenwb/ESnext-experiments/blob/master/ST80collections-exp1.js#L419 ). We may be able to work out the details so we can leave out the property name if it is the same as the current method name, but for now I always explicitly include the name.

# Axel Rauschmayer (12 years ago)

But we could have super(foo) as syntactic sugar for super.constructor(foo), right? Not that I think it matters terribly...

# Allen Wirfs-Brock (12 years ago)

On Oct 30, 2011, at 10:26 AM, Axel Rauschmayer wrote:

Over the last couple years we have explored a lot of variations of how to approach this problem. Most of them are captured on the wiki:

strawman:obj_initialiser_constructors, doku.php?id=strawman:obj_initialiser_class_abstraction&rev=1299955398, strawman:obj_initialiser_class_abstraction

(and other intermediate versions of these and other pages)

Thanks. Note that my idea is more about defining a callable object using object literal syntax.

I know...we experimented with that too. It's hard to find a syntax that isn't acquired in one way or another. Also, there have been concerns expressed about muddling function body and object literal syntax.

# Allen Wirfs-Brock (12 years ago)

On Oct 30, 2011, at 10:39 AM, John J Barton wrote:

In the abstract I would agree, but, in our world, every college sophomore CS student learns a class based language and, in our world, prototypical inheritance in JS uses a bizarre pattern of expression. ES should work make this bizarre pattern unnecessary so prototypical inheritance can shine. Using ".prototype" in new patterns heads in the wrong direction: that is the comment I was making on Allen's proposal.

Note that my "class pattern" that was the topic at the beginning of this thread is not a pattern for expression prototypal inheritance. It is a pattern for expressing "classical" (ie, class-based) inheritance in JavaScript using existing JavaScript terminology and conventions.

If you are primarily interested in prototypal inheritance then you want something else. My "objet exemplar" proposal focus on that.

The complication for all of this, is that we have to accommodate both prototypal and classical forms (and old and new code) and make them work reasonably well together. We Don't have a clean slate to work form.

# Axel Rauschmayer (12 years ago)

The object exemplar approach is just like self or selfish, except that it builds upon features that are already in JS. Specifically, it uses the new operator instead of a new method and it names the initialization method "constructor" in order to tie into the object construction mechanisms that already exist in JS.

I’m trying to summarize, let me know if I made any mistakes:

With the new new approach, we will have four kinds of exemplars (which are, roughly, “object factories”):

  1. Object literals
  2. Function exemplars (constructor exemplars?)
  3. Object exemplars (prototype exemplars?)
  4. Object.create()

The proto operator lets us use inheritance between any two #2 or #3 exemplars. That ensures compatibility with legacy code. Since instanceof works for both kinds of examplars as well, the only possible hazard that is left is function exemplar code trying to access ObjectExamplar.prototype, e.g. to add new methods.

Object exemplar example:

const Person = {
    constructor(name) {
        this.name = name;
    },
    describe() {
        return "Person called "+this.name;
    }
};
const Employee = Person <| {
    constructor(name, title) {
        super.constructor(name);
        this.title = title;
    },
    describe() {
        return super.describe()+" ("+this.title+")";
    }
};

let jane = new Employee();
console.log(jane instanceof Employee); // true

If object exemplars were to become part of ES.next, we would not need class literals.

# Allen Wirfs-Brock (12 years ago)

We would have to have additional internal state to capture the method name ("constructor" or whatever) but we are already doing something similar to capture the super object binding so it isn't inconceivable. We I look at implicit super naming in the past it also appeared to create issues for getter/setter property accesses:

var p = sup <| {get foo() { return super} //is this the same as return super.foo ??? };

# Axel Rauschmayer (12 years ago)

Ah, I just meant for the constructor, for nothing else (Java-style ;-)

If you have function exemplars then the word "constructor" does not appear anywhere, hence leaving it out makes sense. In object exemplars, the word "constructor" is there and there is no need for sugar.

# Rick Waldron (12 years ago)

On Sun, Oct 30, 2011 at 1:16 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:

On Oct 29, 2011, at 5:01 PM, Axel Rauschmayer wrote:

Personally I'd ask whether there is a good reason to have "class" properties on the constructor.

I’m not too fond of them, either. Many current use cases go away with modules. However, sometimes, you want to define class-specific constants such as Point.ZERO.

"class methods" are often used for purposes such as defining secondary factory methods or performing management functions spanning all instances of the class.

It's true that dynamic prototype languages such as self seem to get by fine with only instance methods but they do this by placing behaviors that are not specific to single instances (constant access, factories, etc) on the instances. Class based languages with first-class classes have somewhere else to place such non-instance specific behavior, as methods of the class object. In particular, since "first-class" classes means that classes themselves manifest as objects, they inherently may have methods.

As a prototype inheritance language JavaScript could have followed self-style conventions, but it didn't. In trying to be "Java-like" its core library was organized in a more class like manner including the use of "class methods".

In all languages I have observed, the class methods are used sparingly. A typical class with have one constructor, perhaps several dozen instance methods, and only one or two class methods (many classes have none). Since there are so many fewer class methods than instance methods, it seems acceptable for it to be slightly less convenient to define them then it is to define instance methods.

This conversation seems to have topically converged with the other class-related discussion. ( esdiscuss/2011-October/017680 )

More pointedly, relevant, real-world support for what Allen is describing can be found here:

esdiscuss/2011-October/017727

/

# Jake Verbaten (12 years ago)

the only possible hazard that is left is function exemplar code trying to

access ObjectExamplar.prototype

Could you illustrate where a function exemplar may try to access an ObjectExemplar.prototype property?

Would this be old code that accepts an exemplar as input but expects it to be a function exemplar?

# Axel Rauschmayer (12 years ago)

the only possible hazard that is left is function exemplar code trying to access ObjectExamplar.prototype

Could you illustrate where a function exemplar may try to access an ObjectExemplar.prototype property?

Would this be old code that accepts an exemplar as input but expects it to be a function exemplar?

Yes, this is very unlikely to happen. I was merely thinking along these lines:

  • The following features work for both function exemplars and object exemplars: new, instanceof, <|, super

  • Given this high degree of compatibility, could function exemplar code have expectations for an exemplar that would not be fulfilled by an object exemplar? Accessing exemplar methods was the only thing I could come up with. Thanks to |super|, there is no need to call a super-exemplar like a function, any more (which would be an expectation that object exemplars could not meet).

Axel

# Brendan Eich (12 years ago)

On Oct 30, 2011, at 12:33 PM, Allen Wirfs-Brock wrote:

The object exemplar approach is just like self or selfish, except that it builds upon features that are already in JS. Specifically, it uses the new operator instead of a new method and it names the initialization method "constructor" in order to tie into the object construction mechanisms that already exist in JS.

+1

The only thing I find off the mark is the typography of <|. In light of this, and of the anti-grawlix reaction among many people, could we revisit an infix operator used in restricted productions with [no LineTerminator here] on the left of the operator contextual keyword?

Likely keywords include 'proto' (but 'protos' seems better English given the LHS being the prototype object), or my current best shot: 'beget'.

    let obj = base beget {a: 1, b: 2}
    let arr = base beget [p, q, r]
    let fun = base beget function (...args) { ... }
    let re  = base beget /(\w+)\s+(\w)+/g

It's still idiomatic as a name for differential inheritance, but it is more pithy than 'make' or 'create' (and one character shorter than 'create' -- no Unix 'creat' reruns! ;-). Comments?

Saying or writing "triangle" does not convey meaning, and it's confusing in geometry/graphics contexts.

While I still think 'class' is easier to teach, there's a risk if JS has 'class' syntax that desugars to constructors with prototypes. And with your exemplar proposal, if we're really going to level the prototype/constructor playing field, then we need more than 'new'/'constructor' protocols for objects as well as functions. We need 'beget'.

# Allen Wirfs-Brock (12 years ago)

On Oct 30, 2011, at 1:12 PM, Axel Rauschmayer wrote:

The object exemplar approach is just like self or selfish, except that it builds upon features that are already in JS. Specifically, it uses the new operator instead of a new method and it names the initialization method "constructor" in order to tie into the object construction mechanisms that already exist in JS.

I’m trying to summarize, let me know if I made any mistakes:

With the new new approach, we will have four kinds of exemplars (which are, roughly, “object factories”):

  1. Object literals

I'm not sure I would classify a simple, unnamed object literal as an "exemplar". When I introduce this term I had in mind a construct for expressing a named abstraction over a set of similar objects. The name part is important because it is the name that allows talk about the set rather than the individual object in the set. Object literals might be used as constituent elements in the definition but are not by them selves exemplars.

  1. Function exemplars (constructor exemplars?)
  2. Object exemplars (prototype exemplars?)
  3. Object.create()

I would consider (demote) Object.create to simply be part of the languages reflection API rather than an actual language element. As such, we may not need to include it in this consideration.

# Allen Wirfs-Brock (12 years ago)

On Oct 30, 2011, at 1:17 PM, Axel Rauschmayer wrote:

Ah, I just meant for the constructor, for nothing else (Java-style ;-)

If you have function exemplars then the word "constructor" does not appear anywhere, hence leaving it out makes sense. In object exemplars, the word "constructor" is there and there is no need for sugar.

function exemplars are implicitly set as the value of a property name "constructor" in all the forms that have been discussed. so while it isn't explicit, it is very real.

I generally thing we will either have always or never allow for an implicit property name following super.

# Axel Rauschmayer (12 years ago)

Thanks. But it is function exemplar versus object exemplar and not constructor exemplar versus prototype exemplar. Right?

# Axel Rauschmayer (12 years ago)

The only thing I find off the mark is the typography of <|. In light of this, and of the anti-grawlix reaction among many people, could we revisit an infix operator used in restricted productions with [no LineTerminator here] on the left of the operator contextual keyword?

I hope this is not just in deference to a few vocal opponents. Valid reasons for changing the operator are: a majority demands it or the change helps make it politically viable. I, for one, like the way it looks and find it highly intuitive: it looks like an arrow. And when I draw object diagrams, I draw pointers from an object to its prototype.

Likely keywords include 'proto' (but 'protos' seems better English given the LHS being the prototype object), or my current best shot: 'beget'.

   let obj = base beget {a: 1, b: 2}
   let arr = base beget [p, q, r]
   let fun = base beget function (...args) { ... }
   let re  = base beget /(\w+)\s+(\w)+/g

How about subsumes (as the inverse of “extends”)?

   let obj = base subsumes {a: 1, b: 2}
   let arr = base subsumes [p, q, r]
   let fun = base subsumes function (...args) { ... }
   let re  = base subsumes /(\w+)\s+(\w)+/g

A bit long, but reads nicely.

# Allen Wirfs-Brock (12 years ago)

On Oct 30, 2011, at 3:36 PM, Brendan Eich wrote:

On Oct 30, 2011, at 12:33 PM, Allen Wirfs-Brock wrote:

The object exemplar approach is just like self or selfish, except that it builds upon features that are already in JS. Specifically, it uses the new operator instead of a new method and it names the initialization method "constructor" in order to tie into the object construction mechanisms that already exist in JS.

+1

The only thing I find off the mark is the typography of <|. In light of this, and of the anti-grawlix reaction among many people, could we revisit an infix operator used in restricted productions with [no LineTerminator here] on the left of the operator contextual keyword?

I still think that <: might be an reasonable alternative, however it too will have typography issues in some fonts.

Likely keywords include 'proto' (but 'protos' seems better English given the LHS being the prototype object), or my current best shot: 'beget'.

   let obj = base beget {a: 1, b: 2}
   let arr = base beget [p, q, r]
   let fun = base beget function (...args) { ... }
   let re  = base beget /(\w+)\s+(\w)+/g

It's still idiomatic as a name for differential inheritance, but it is more pithy than 'make' or 'create' (and one character shorter than 'create' -- no Unix 'creat' reruns! ;-). Comments?

Of the various keywords that I been suggested for this operator, I think I like it the best. It is probably good that it is fairly unique and idiomatic.

Saying or writing "triangle" does not convey meaning, and it's confusing in geometry/graphics contexts.

yes, my original suggest is that <| should be produced "prototype for"

While I still think 'class' is easier to teach, there's a risk if JS has 'class' syntax that desugars to constructors with prototypes. And with your exemplar proposal, if we're really going to level the prototype/constructor playing field, then we need more than 'new'/'constructor' protocols for objects as well as functions. We need 'beget'.

I kind of like the rationale of: You (JS users) asked for "classes" but they really don't fit very well with the core concepts of the language we have to build upon. We understand that what you really need is an expressive way to define named abstractions over objects and that is something that we can provide. The mechanism are a little different from in a class based language, but actually quite similar.

# Allen Wirfs-Brock (12 years ago)

On Oct 30, 2011, at 5:47 PM, Axel Rauschmayer wrote:

Thanks. But it is function exemplar versus object exemplar and not constructor exemplar versus prototype exemplar. Right?

I think when I originally introduced the exemplar term I contrasted function exemplars (fExemplars) with object exemplars (oExemplars) because one is based upon function expressions and the other is based upon object literals.

Both forms involved the use of "prototype" objects with a method named "constructor".

# Axel Rauschmayer (12 years ago)
  let obj = base beget {a: 1, b: 2}
  let arr = base beget [p, q, r]
  let fun = base beget function (...args) { ... }
  let re  = base beget /(\w+)\s+(\w)+/g

It's still idiomatic as a name for differential inheritance, but it is more pithy than 'make' or 'create' (and one character shorter than 'create' -- no Unix 'creat' reruns! ;-). Comments?

Of the various keywords that I been suggested for this operator, I think I like it the best. It is probably good that it is fairly unique and idiomatic.

Saying or writing "triangle" does not convey meaning, and it's confusing in geometry/graphics contexts.

yes, my original suggest is that <| should be produced "prototype for"

One last idea, then I’ll stop my bikeshedding:

I think it helps if it reads well. For example:

const Employee = Person refinedBy { ... } const Employee = Person subsuming { ... } const Employee = Person parenting { ... } const Employee = Person above { ... } const Employee = Person before { ... }

The above examples are almost English (well, to programmers, anyway).

# Axel Rauschmayer (12 years ago)

Both might make sense. I would say that the term X exemplar means that you use X to produce instances. Thus:

  1. Using the constructor versus using the prototype to produce an instance. “Constructors as classes” versus “prototypes as classes”.
  2. Using a function versus using an object to produce an instance.

I like object exemplar and function exemplar, because they are the more direct descriptions.

# Juan Ignacio Dopazo (12 years ago)

On Sun, Oct 30, 2011 at 10:13 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:

I kind of like the rationale of: You (JS users) asked for "classes" but they really don't fit very well with the core concepts of the languagewe have to build upon. Allen

Why? We have seen in more than one occasion how they do fit well.

Juan

# Axel Rauschmayer (12 years ago)

Are you arguing against prototypes (which are the foundation of both function exemplars and object exemplars)?

# Brendan Eich (12 years ago)

On Oct 30, 2011, at 5:55 PM, Axel Rauschmayer wrote:

The only thing I find off the mark is the typography of <|. In light of this, and of the anti-grawlix reaction among many people, could we revisit an infix operator used in restricted productions with [no LineTerminator here] on the left of the operator contextual keyword?

I hope this is not just in deference to a few vocal opponents.

That's not the way to approach this. You could be among the few vocal proponents of <| -- do we need a statistically significant and valid survey?

There are plenty of fonts in which the triangle appearance is ugly or lost. There are people who object independent of fonts to JS growing line-noise hair at its advanced age. These are both worth considering. They can't be dismissed with "few" and "vocal".

Likely keywords include 'proto' (but 'protos' seems better English given the LHS being the prototype object), or my current best shot: 'beget'.

  let obj = base beget {a: 1, b: 2}
  let arr = base beget [p, q, r]
  let fun = base beget function (...args) { ... }
  let re  = base beget /(\w+)\s+(\w)+/g

How about subsumes (as the inverse of “extends”)?

  let obj = base subsumes {a: 1, b: 2}
  let arr = base subsumes [p, q, r]
  let fun = base subsumes function (...args) { ... }
  let re  = base subsumes /(\w+)\s+(\w)+/g

That doesn't work in two ways:

  1. proto-linking is not subsumption in any set theoretic or dictionary ("To have as a part") sense. base does not have as a part the literal on the right. Rather, proto-linking is JS's differential inheritance solution.

  2. "subsumes" is too long and novel. "beget" has history thanks to Crock. We could even have an Object.beget as the easy-to-use Object.create analogue -- it would have to copy its second parameter in general (it couldn't restrict the second parameter to be passed as a literal).

# Brendan Eich (12 years ago)

On Oct 30, 2011, at 6:19 PM, Axel Rauschmayer wrote:

  let obj = base beget {a: 1, b: 2}
  let arr = base beget [p, q, r]
  let fun = base beget function (...args) { ... }
  let re  = base beget /(\w+)\s+(\w)+/g

It's still idiomatic as a name for differential inheritance, but it is more pithy than 'make' or 'create' (and one character shorter than 'create' -- no Unix 'creat' reruns! ;-). Comments?

Of the various keywords that I been suggested for this operator, I think I like it the best. It is probably good that it is fairly unique and idiomatic.

Saying or writing "triangle" does not convey meaning, and it's confusing in geometry/graphics contexts.

yes, my original suggest is that <| should be produced "prototype for"

One last idea, then I’ll stop my bikeshedding:

I think it helps if it reads well. For example:

const Employee = Person refinedBy { ... } const Employee = Person subsuming { ... } const Employee = Person parenting { ... } const Employee = Person above { ... } const Employee = Person before { ... }

Sorry, these are ghastly (it's almost Halloween, but c'mon).

I searched a bit and re-read Smalltalk, Self, Cecil, and Io docs to get a handle on what <| does. It is not 'clone'. It ain't 'create' except in a vacuous sense that's also already "taken" by ES5 Object.create. It isn't "subsuming" in my view. "refinedBy" is closer but you'll get camelCaps keywords into JS over my dead body!

I landed on 'beget' because 'create' is close but vague yet poisoned, and we need something pithy. Doug already employed it ages ago. Is there a reason you don't like 'beget'?

# Brendan Eich (12 years ago)

On Oct 30, 2011, at 11:11 PM, Brendan Eich wrote:

I searched a bit and re-read Smalltalk, Self, Cecil, and Io docs to get a handle on what <| does. It is not 'clone'.

It's not 'copy' (Self) either, clearly.

It ain't 'create' except in a vacuous sense that's also already "taken" by ES5 Object.create. It isn't "subsuming" in my view. "refinedBy" is closer but you'll get camelCaps keywords into JS over my dead body!

I landed on 'beget' because 'create' is close but vague yet poisoned, and we need something pithy.

Also, 'beget' does match the "sire" or "hatch" connotation of taking a parent (Self again) object and differentialy inheriting another object from it via proto-linking. Clone means make a twin and mutate. Copy is, well, just a copy -- arguably close to clone and one char shorter (so Self chose well). What we have with <| is more like "generate a child" -- hence, 'beget'.

# Jorge (12 years ago)

On 30/10/2011, at 23:36, Brendan Eich wrote:

On Oct 30, 2011, at 12:33 PM, Allen Wirfs-Brock wrote:

The object exemplar approach is just like self or selfish, except that it builds upon features that are already in JS. Specifically, it uses the new operator instead of a new method and it names the initialization method "constructor" in order to tie into the object construction mechanisms that already exist in JS.

+1

The only thing I find off the mark is the typography of <|. In light of this, and of the anti-grawlix reaction among many people, could we revisit an infix operator used in restricted productions with [no LineTerminator here] on the left of the operator contextual keyword?

Likely keywords include 'proto' (but 'protos' seems better English given the LHS being the prototype object), or my current best shot: 'beget'.

   let obj = base beget {a: 1, b: 2}
   let arr = base beget [p, q, r]
   let fun = base beget function (...args) { ... }
   let re  = base beget /(\w+)\s+(\w)+/g

It's still idiomatic as a name for differential inheritance, but it is more pithy than 'make' or 'create' (and one character shorter than 'create' -- no Unix 'creat' reruns! ;-). Comments?

Saying or writing "triangle" does not convey meaning, and it's confusing in geometry/graphics contexts.

Perhaps a long arrow may work ?

let object= base <== {a: 1, b: 2};

# Brendan Eich (12 years ago)

Does not overcome the grawlix objection.

# Claus Reinke (12 years ago)

The only thing I find off the mark is the typography of <|. In light of this, and of the anti-grawlix reaction among many people, could we revisit an infix operator used in restricted productions with [no LineTerminator here] on the left of the operator contextual keyword?

Am I the only one who flinches when someone mentions adding another [no LineTerminator here]?

Apart from adding to ASI fun (the less of which, the better), these suggestions are phrases, to be written in a certain layout. That is different from infix operators, and even infix operators are not as flexible as I'd like in JS (can't easily pass them as parameters, for a start).

To balance the 'anti-grawlix' slogan, perhaps we should try to coin a counter-meme. How about 'cobol.js' for English-like infix operator phrases that aren't really infix operators, and aren't really English.

As observed by Wadler, syntax details draw the most replies in language design discussions

http://lambda-the-ultimate.org/node/4287

So, much as I'd like to, I'll not express my preferences on the syntax here. Instead, I'd like to call attention to some of the semantic, pragmatic, and organizational aspects that are still troubling me:

  • there are several parts of code that would be awkward to abstract over (restriction to object literals, infix operators), or make it difficult to use the new features in expression- oriented styles (in-place modification);

    these surface issues are pointing to deeper language design issues that have not been tackled yet (object cloning/copying, user-defined infix operators and conversion between infix operators and prefix functions)

  • infix operators fall into that hole of macros-later, value proxies later, no user-defined infix ops; it is interesting how much time is spent on specific infix operator questions here, given that some committee members were opposed to a general solution

  • the only argument against generalizing from object literals and avoiding in-place update was that cloning/ copying would be non-trivial to get right;

    but that non-triviality seems to me a very good reason why the language standard should have something to say about the topic; it comes up in several contexts;

    if you don't want to commit to deep or shallow or whatever forms of cloning/copying yet, how about defining the several possible forms, and providing operators/functions for them?

Btw: several of my messages have not yet appeared on es-discuss, and es-discuss-owner is unresponsive.

Claus clausreinke.github.com, clausreinke.github.com/js-tools

# David Bruant (12 years ago)

Le 30/10/2011 23:36, Brendan Eich a écrit :

On Oct 30, 2011, at 12:33 PM, Allen Wirfs-Brock wrote:

The object exemplar approach is just like self or selfish, except that it builds upon features that are already in JS. Specifically, it uses the new operator instead of a new method and it names the initialization method "constructor" in order to tie into the object construction mechanisms that already exist in JS. +1

The only thing I find off the mark is the typography of <|. In light of this, and of the anti-grawlix reaction among many people, could we revisit an infix operator used in restricted productions with [no LineTerminator here] on the left of the operator contextual keyword?

Likely keywords include 'proto' (but 'protos' seems better English given the LHS being the prototype object)

What about 'protoOf'? Operators are not camelcase ('typeof', 'instanceof'). Maybe 'protoof', but since 'proto' ends in 'o', it doesn't look very good to me (though I'm nit an native English speaker)

let o = base protoof {a:1, b:2}; let a = base protoof [1, 2, 3];

Or,

let o = base protoOf {a:1, b:2}; let a = base protoOf [1, 2, 3]; ?

I would have suggested 'prototypeof' in reference to Object.getPrototypeOf, but I find it a bit long.

Ideas?

# Axel Rauschmayer (12 years ago)

I think it helps if it reads well. For example:

const Employee = Person refinedBy { ... } const Employee = Person subsuming { ... } const Employee = Person parenting { ... } const Employee = Person above { ... } const Employee = Person before { ... }

Sorry, these are ghastly (it's almost Halloween, but c'mon).

I searched a bit and re-read Smalltalk, Self, Cecil, and Io docs to get a handle on what <| does. It is not 'clone'. It ain't 'create' except in a vacuous sense that's also already "taken" by ES5 Object.create. It isn't "subsuming" in my view. "refinedBy" is closer but you'll get camelCaps keywords into JS over my dead body!

const Employee = Person refinedby { ... }
const Employee = Person refby { ... }
const Employee = Person by { ... }

(Precedence: instanceof)

I landed on 'beget' because 'create' is close but vague yet poisoned, and we need something pithy. Doug already employed it ages ago. Is there a reason you don't like 'beget'?

Only one: It does not read like English (unless you read it like a command). How about:

const Employee = Person begets {}

But I will be so glad to have this operator, I don’t mind too much about the actual name. I wouldn’t rule out "proto", yet, though. To be read as “is prototype of”.

I’m surprised that the anti-Grawlix faction is so passionate – using a < like operator for inheritance has a long tradition in theoretical computer science.

Adding a non-grawlix name to Object is a good argument against something grawlixy, though.

# David Bruant (12 years ago)

Le 31/10/2011 07:20, Brendan Eich a écrit :

On Oct 30, 2011, at 11:11 PM, Brendan Eich wrote:

It ain't 'create' except in a vacuous sense that's also already "taken" by ES5 Object.create. It isn't "subsuming" in my view. "refinedBy" is closer but you'll get camelCaps keywords into JS over my dead body!

I landed on 'beget' because 'create' is close but vague yet poisoned, and we need something pithy. Doug already employed it ages ago. Is there a reason you don't like 'beget'? Also, 'beget' does match the "sire" or "hatch" connotation of taking a parent (Self again) object and differentialy inheriting another object from it via proto-linking. Clone means make a twin and mutate. Copy is, well, just a copy -- arguably close to clone and one char shorter (so Self chose well). What we have with <| is more like "generate a child" -- hence, 'beget'.

Asking Google for "beget":

Verb: (typically of a man, sometimes of a man and a woman) Bring (a child) into existence by the process of reproduction. Give rise to; bring about.

Synonyms:
generate - breed - procreate - engender - father

It sounds indeed very much what you mean. I had to look up, because I, as a non-native English speaker had never come across the word "beget". I had seen some JS libraries which used that word (which I thought was specific to the library). I think it would be interested to know what other non-native English speaker think of beget. While operators like "typeof" or "instanceof" have a pretty straightforward meaning, "beget" sounds more difficult to grasp for non-native speakers, even those who are familiar with programming (I had decent experience in C, C++, Java and Lisp before starting with JavaScript).

"beget" sounds very much like what we want, but I just wanted to raise a point about understanding and adoption, especially for the language of the web.

Allen:

my original suggest is that <| should be produced "prototype for"

What about 'protofor'? let obj = base protofor {a: 1, b: 2} let arr = base protofor [p, q, r] let fun = base protofor function (...args) { ... } let re = base protofor /(\w+)\s+(\w)+/g

Once again, for the specific case of functions, the proto operator has a semantics that goes way beyond setting the [[prototype]] internal property. Maybe 'protofor' for the [[prototype]] and 'beget' for the constructor-related semantics?

# Axel Rauschmayer (12 years ago)

I searched a bit and re-read Smalltalk, Self, Cecil, and Io docs to get a handle on what <| does. It is not 'clone'.

It's not 'copy' (Self) either, clearly.

It ain't 'create' except in a vacuous sense that's also already "taken" by ES5 Object.create. It isn't "subsuming" in my view. "refinedBy" is closer but you'll get camelCaps keywords into JS over my dead body!

I landed on 'beget' because 'create' is close but vague yet poisoned, and we need something pithy.

Also, 'beget' does match the "sire" or "hatch" connotation of taking a parent (Self again) object and differentialy inheriting another object from it via proto-linking. Clone means make a twin and mutate. Copy is, well, just a copy -- arguably close to clone and one char shorter (so Self chose well). What we have with <| is more like "generate a child" -- hence, 'beget'.

Two more ideas:

const Employee = Person to { ... } // or any other preposition (prepositions are like operators) const Employee = Person parents { ... }

# Quildreen Motta (12 years ago)

I still think <| is more straight-forward to grasp to non-native speakers -- they're likely to have stumbled upon that on UML classes, methinks. Also, there's the problem of creating new reserved words in the languages, imho it makes a language feel heavier and clunkier. I think one of the greatest point of ECMAScript is that, despite the awful amount of reserved words, the language still manages to be simple and straight forward for people to grasp, except for a few semantic quirks here and there.

I don't think that evolution and simplicity have to be mutually exclusive. Languages should strive to hide the perceived complexity from the end-user, while still managing to be expressive. If we decide on using a keyword for expressing <|, this word should be as straight-forward and simple to grasp for both native english-speaking people and non-native english-speaking people, which I don't think any of the proposed words are =/

2011/10/31 Axel Rauschmayer <axel at rauschma.de>

# Axel Rauschmayer (12 years ago)

"beget" sounds very much like what we want, but I just wanted to raise a point about understanding and adoption, especially for the language of the web.

I wouldn’t worry, all of a programming language is new vocabulary, anyway. You always have to learn semantics, so learning a new word (especially one that increases your English vocabulary) shouldn’t be a problem. My worry is more that it doesn’t read like a sentence. I would prefer

const Employee = Person begets { ... };

I think Java got it right with extends:

class Employee extends Person { ... }

What about 'protofor'? let obj = base protofor {a: 1, b: 2} let arr = base protofor [p, q, r] let fun = base protofor function (...args) { ... } let re = base protofor /(\w+)\s+(\w)+/g

Once again, for the specific case of functions, the proto operator has a semantics that goes way beyond setting the [[prototype]] internal property. Maybe 'protofor' for the [[prototype]] and 'beget' for the constructor-related semantics?

Even though it contradicts my previous rules, I still tremendously like “proto”: It does not create new vocabulary and has an operator-y feel to it.

   let obj = base proto {a: 1, b: 2}
   let arr = base proto [p, q, r]
   let fun = base proto function (...args) { ... }
   let re  = base proto /(\w+)\s+(\w)+/g
# Rick Waldron (12 years ago)

"begets" is pure win. i.word.com/idictionary/beget, it's pronounceable and searchable/google-able (being able to find new syntax docs is crucial). It has a known history and follows an existing grammar precedent.

Perhaps least importantly, I feel like a can get excited about "begets"

/

# Axel Rauschmayer (12 years ago)

"begets" is pure win. i.word.com/idictionary/beget, it's pronounceable and searchable/google-able (being able to find new syntax docs is crucial). It has a known history and follows an existing grammar precedent.

Perhaps least importantly, I feel like a can get excited about "begets"

let obj = base begets {a: 1, b: 2}
let arr = base begets [p, q, r]
let fun = base begets function (...args) { ... }
let re  = base begets /(\w+)\s+(\w)+/g
let Employee  = Person begets { ... }

Three positive aspects of begets:

  • begets (as opposed to “beget”) in the above examples reads like English.
  • We have created a handy new word for talking about prototypal inheritance: a prototype begets an object, an object is begotten (sic?) by its prototype.
  • It works the same for “subclassing” and for creating instances (singleton instances, otherwise, you would use “new”).

If people manage to get over their class bias (which is hard, because we have been exposed to classes so much) then “begets” is a much more natural way of doing things, because you always directly work with and connect objects.

# Allen Wirfs-Brock (12 years ago)

On Oct 30, 2011, at 11:20 PM, Brendan Eich wrote:

I landed on 'beget' because 'create' is close but vague yet poisoned, and we need something pithy.

Also, 'beget' does match the "sire" or "hatch" connotation of taking a parent (Self again) object and differentialy inheriting another object from it via proto-linking. Clone means make a twin and mutate. Copy is, well, just a copy -- arguably close to clone and one char shorter (so Self chose well). What we have with <| is more like "generate a child" -- hence, 'beget'.

I've (very) briefly considered "sires" as it has the right connotation.

some others (probably all too long for Brendan's tastes):

"provides" (properties for) "provisions" "generalizes" "derives" "spawns" "engenders" "differentiates"

"spawn" (bad concurrency connotations) "parent" (bad DOM connotations)

Not accurately descriptive but close enough that they have some of the right connotations. "build" "devise" "forge" "form" "invest"

Note that for many non-native English speakers probably don't have many of these words (including beget) in their vocabularies. For them, a symbolic token such as <| or <: is probably just as meaningful.

# Allen Wirfs-Brock (12 years ago)

On Oct 31, 2011, at 5:45 AM, Axel Rauschmayer wrote:

"beget" sounds very much like what we want, but I just wanted to raise a point about understanding and adoption, especially for the language of the web.

I wouldn’t worry, all of a programming language is new vocabulary, anyway. You always have to learn semantics, so learning a new word (especially one that increases your English vocabulary) shouldn’t be a problem.

If this logic is correct then we shouldn't be worrying about the word choice at all. We can just make up a word. I propose "wrfs" as a suitably short and meaningless word that isn't biased in favor of English speakers.

Allenb

# Neil Eades (12 years ago)

On 31 October 2011 15:23, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:

some others (probably all too long for Brendan's tastes):

I would assume a two word combination such as "super for" would be too verbose to be acceptable.

# Allen Wirfs-Brock (12 years ago)

On Oct 30, 2011, at 11:07 PM, Brendan Eich wrote:

On Oct 30, 2011, at 5:55 PM, Axel Rauschmayer wrote:

The only thing I find off the mark is the typography of <|. In light of this, and of the anti-grawlix reaction among many people, could we revisit an infix operator used in restricted productions with [no LineTerminator here] on the left of the operator contextual keyword?

I hope this is not just in deference to a few vocal opponents.

That's not the way to approach this. You could be among the few vocal proponents of <| -- do we need a statistically significant and valid survey?

There are plenty of fonts in which the triangle appearance is ugly or lost. There are people who object independent of fonts to JS growing line-noise hair at its advanced age. These are both worth considering. They can't be dismissed with "few" and "vocal".

I've heard the "line noise" objection many time but I don't understand the thinking that seems to say you can only introduce new symbology into a language at its initial creation and that all post initial release extensions must be natural language based.

<| or <: or "beget" is going to be a very important "operator" going forward and is used in expression context where the norm is special character-based operators. Adding a new symbol for such an operator seems quite reasonable. Wholesale re-grawlix-ifying the entire language would be unacceptable. Adding one or two new symbols for key features is not that.

# Brendan Eich (12 years ago)

We've been over this before.

  1. No camelCaps.
  2. No "oof" substrings (comical!).
  3. No prepositional phrases that suggest predicates, where active verbs are requried.
# Axel Rauschmayer (12 years ago)

"beget" sounds very much like what we want, but I just wanted to raise a point about understanding and adoption, especially for the language of the web.

I wouldn’t worry, all of a programming language is new vocabulary, anyway. You always have to learn semantics, so learning a new word (especially one that increases your English vocabulary) shouldn’t be a problem.

If this logic is correct then we shouldn't be worrying about the word choice at all. We can just make up a word. I propose "wrfs" as a suitably short and meaningless word that isn't biased in favor of English speakers.

I like brck better. ;-)

I should clarify – what I actually meant is: You can’t worry about all non-native speakers ("super" and "sub" must be challenging to someone whose language has not been influenced by Latin, etc.). I’ve heard about beget (“violence only begets violence”, IIRC) and it’s a combination of two easy words, so it shouldn’t be too hard to learn. I think it’s too late to remove the English bias from JavaScript (kudos to Oracle for trying – they call their JavaScript engine Nashorn).

# Allen Wirfs-Brock (12 years ago)

On Oct 31, 2011, at 9:07 AM, Axel Rauschmayer wrote:

"beget" sounds very much like what we want, but I just wanted to raise a point about understanding and adoption, especially for the language of the web.

I wouldn’t worry, all of a programming language is new vocabulary, anyway. You always have to learn semantics, so learning a new word (especially one that increases your English vocabulary) shouldn’t be a problem.

If this logic is correct then we shouldn't be worrying about the word choice at all. We can just make up a word. I propose "wrfs" as a suitably short and meaningless word that isn't biased in favor of English speakers.

I like brck better. ;-)

maybe we can compromise on wrfsbrck or brckwrfs

# Axel Rauschmayer (12 years ago)

I like all of them (“form” does have DOM connotations, though), the last ones should be in third person.

Brendan’s “protos” could work, too, as an abbreviation for “prototypes”.

# John J Barton (12 years ago)

On Sun, Oct 30, 2011 at 12:33 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:

On Oct 29, 2011, at 10:03 PM, John J Barton wrote: ...

JS is what it is. I don't think it is possible to make prototypes disappear without breaking many (most??) existing JS programs.

(This perfectly illustrates my objection to any new features using the word "prototype"). I assume you meant "to make |.prototype| disappear" rather than "to make prototypical inheritance disappear". I am not suggesting removing |.prototype|; I am suggesting that it be avoided in future work because by now we have a lot of experience with it and its not a good thing.

I'd love to see a riff on Gozala's selfish with the declarative approach. Maybe the gap is too large.

It has been proposed in many variations.

The basic way that object abstractions are instantiated in the self language is via a copy/initialize sequence. You send a copy message to a Prototype object, typically this creates a new object that inherits form the Prototype and then invokes the initialize method on the new object to set up and instance specific state.

In selfish, the "new" method is the equivalent of self's "copy" method and selfish's "initialize" method serves a similar role to self's "initialize" method. If you have to define a lot of methods (typically because the object you are defining is going to be used as a Prototype), it's inconvenient to do this in the initialize method, so both self and selfish provide a way to directly define a new Prototype object. In self, this is via its IDE and reflection API. In selfish it is via the "extend" method.

The "object exemplar" proposal I have talked about also exactly parallels this same self/selfish model. With object exemplars, the JS new operator corresponds to self's "copy" and selfish's "new" method. With object exemplars the "constructor" method corresponds to the self/selfish "initialize" method.

So where in self you would: Derive a new prototype object named Dog from a prototype named Mammal using the IDE. Create a Dog instance by saying: Dog new: 'Labrador' which creates a new object that inherits from Dog. The "initialize method is invoked on the new instance passing "Labrador" as the argument.

In selfish you would: Derive a new prototype named Dog by evaluating: var Dog = Mammal.extend ({ initialize: function(breed) {this.breed = breed}, /* other dog methods */ }); You would create a Dog instance by saying Dog.new("Labrador") which creates a new object that inherits from Dog. The "initialize" method is invoked on the new instance passing "Labrador" as the argument.

In JS using my object exemplar proposal you would: Derive a new prototype named Dog by evaluating: var Dog = Mammal <| { constructor: function(breed) {this.breed = breed}, /* other dog methods */ }); You would create a Dog instance by saying new Dog("Labrador") which creates a new object that inherits from Dog. The "constructor" method is invoked on the new instance passing "Labrador" as the argument.

The object exemplar approach is just like self or selfish, except that it builds upon features that are already in JS. Specifically, it uses the new operator instead of a new method and it names the initialization method "constructor" in order to tie into the object construction mechanisms that already exist in JS.

Thanks for the excellent summary and parallel constructions. However you missed my point. None of your examples include |.prototype|, 'dot prototype'. "constructor" vs "initialize" is minor, |.new| vs "operator new" is minor. |.prototype|, with it's confusing relationship to objects and its vocabulary distortions is not minor. Note that your examples above are all clear and the property |.prototype| does not appear.

jjb

# Brendan Eich (12 years ago)

On Oct 31, 2011, at 5:40 AM, Quildreen Motta wrote:

I still think <| is more straight-forward to grasp to non-native speakers -- they're likely to have stumbled upon that on UML classes, methinks. Also, there's the problem of creating new reserved words in the languages, imho it makes a language feel heavier and clunkier. I think one of the greatest point of ECMAScript is that, despite the awful amount of reserved words,

The original language had only:

delete else false for function if in new null return this true typeof var void while with

Ah, memories! Then came ES3, which added:

break case catch continue default do finally instanceof switch throw try

for 28 total. Still not bad in my book.

the language still manages to be simple and straight forward for people to grasp,

I beg to differ. The language is deceptively simple and usually forgiving, but as many deep thinkers have noted, it has depths that take years to plumb. Closures by themselves take study and practice to master.

except for a few semantic quirks here and there.

Of course. (One thing I laugh at is the dog-piling on JS -- as if no other real language had quirks! dmr, bless him, talked about C's quirks frankly at plan9.bell-labs.com/who/dmr/chist.html.)

I don't think that evolution and simplicity have to be mutually exclusive. Languages should strive to hide the perceived complexity from the end-user, while still managing to be expressive. If we decide on using a keyword for expressing <|, this word should be as straight-forward and simple to grasp for both native english-speaking people and non-native english-speaking people, which I don't think any of the proposed words are =/

I want a Pony too.

We're not going to have a universal, English-free syntax. Not in my lifetime, anyway. 'switch' is hardly self-documenting. Even 'for' is overloaded and idiomatic (from C and awk, or Python if you squint really hard). Languages require learning, there's no avoidin it. They do not explain themselves, certainly not in arbitrary native tongues.

# John J Barton (12 years ago)

On Sun, Oct 30, 2011 at 1:08 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:

On Oct 30, 2011, at 10:39 AM, John J Barton wrote:

In the abstract I would agree, but, in our world, every college sophomore CS student learns a class based language and, in our world, prototypical inheritance in JS uses a bizarre pattern of expression. ES should work make this bizarre pattern unnecessary so prototypical inheritance can shine. Using ".prototype" in new patterns heads in the wrong direction: that is the comment I was making on Allen's proposal.

Note that my "class pattern" that was the topic at the beginning of this thread is not a pattern for expression prototypal inheritance. It is a pattern for expressing "classical" (ie, class-based) inheritance in JavaScript using existing JavaScript terminology and conventions.

Thanks for that clarification. So now I just object to this entire enterprise ;-).

In my opinion for new syntax to support classical inheritance should 1) target beginners and 2) help avoid the need for F.prototype/new F() pattern for simple inheritance. Creating a new, complex machine to support classical inheritance will result in lots of language discussions and a new round of libraries to work around the complexities.

jjb

# Brendan Eich (12 years ago)

On Oct 31, 2011, at 5:45 AM, Axel Rauschmayer wrote:

"beget" sounds very much like what we want, but I just wanted to raise a point about understanding and adoption, especially for the language of the web.

I wouldn’t worry, all of a programming language is new vocabulary, anyway. You always have to learn semantics, so learning a new word (especially one that increases your English vocabulary) shouldn’t be a problem. My worry is more that it doesn’t read like a sentence. I would prefer

const Employee = Person begets { ... };

That's an operator, it happens in an evaluation regime at a certain time. It should use a pidgin-English word or phrase free of tense elaboration, as delete, in, instanceof do.

I think Java got it right with extends:

class Employee extends Person { ... }

That's a declarative form, not an operator. It uses present tense to connote timelessness, for all time (once the declaration has been processed).

# Brendan Eich (12 years ago)

On Oct 31, 2011, at 8:49 AM, Allen Wirfs-Brock wrote:

On Oct 30, 2011, at 11:07 PM, Brendan Eich wrote:

On Oct 30, 2011, at 5:55 PM, Axel Rauschmayer wrote:

The only thing I find off the mark is the typography of <|. In light of this, and of the anti-grawlix reaction among many people, could we revisit an infix operator used in restricted productions with [no LineTerminator here] on the left of the operator contextual keyword?

I hope this is not just in deference to a few vocal opponents.

That's not the way to approach this. You could be among the few vocal proponents of <| -- do we need a statistically significant and valid survey?

There are plenty of fonts in which the triangle appearance is ugly or lost. There are people who object independent of fonts to JS growing line-noise hair at its advanced age. These are both worth considering. They can't be dismissed with "few" and "vocal".

I've heard the "line noise" objection many time but I don't understand the thinking that seems to say you can only introduce new symbology into a language at its initial creation and that all post initial release extensions must be natural language based.

That's too dogmatic, I agree.

The grawlix objection was not a rigorous one, rather an outcry against a tendency that can be overdone. And which bites back hard in some fonts. The typography issue persists.

<| or <: or "beget" is going to be a very important "operator" going forward and is used in expression context where the norm is special character-based operators. Adding a new symbol for such an operator seems quite reasonable. Wholesale re-grawlix-ifying the entire language would be unacceptable. Adding one or two new symbols for key features is not that.

No, but if the typography and quantity of punctuation-pairings is off enough, there'll be push-back and ongoing controversy. I don't see this one solving itself by exposure and familiarity.

If we had a more universally triangular (pointing left) sequence, probably we wouldn't be here. My gut-check, FWIW.

# Axel Rauschmayer (12 years ago)

My worry is more that it doesn’t read like a sentence. I would prefer

const Employee = Person begets { ... };

That's an operator, it happens in an evaluation regime at a certain time. It should use a pidgin-English word or phrase free of tense elaboration, as delete, in, instanceof do

I’m not sure what the best approach is. One more idea: The examples you give are easily turned into English.

 delete foo.bar => Delete foo.bar!
 "bar" in foo => Is "bar" in foo?
 obj instanceof Constr => Is obj an instanceof Constr?

I think that’s why they work so well. How would you do the same for “beget”? But “begets” isn’t any better. Maybe “begetting”? The result can indeed be described as Person begetting an object.

 Person beget { ... } => ???

Is beget an imperative here or an infinitive?

# Brendan Eich (12 years ago)

On Oct 31, 2011, at 9:45 AM, John J Barton wrote:

In my opinion for new syntax to support classical inheritance should 1) target beginners and 2) help avoid the need for F.prototype/new F() pattern for simple inheritance.

John, I almost-completely agree with you (yay!), except for the |new F| objection. What's wrong with operator new for class instantiation?

# Brendan Eich (12 years ago)

On Oct 31, 2011, at 9:59 AM, Axel Rauschmayer wrote:

 Person beget { ... } => ???

Is beget an imperative here or an infinitive?

Both! But it's not a declarative present-tense linking form, as "extends" is in class declarations (I think "class literals" is a terrible phrase, BTW -- too many evaluated parts and mutability to be a "literal").

# Jorge (12 years ago)

On 31/10/2011, at 08:57, Brendan Eich wrote:

On Oct 31, 2011, at 12:20 AM, Jorge wrote:

Perhaps a long arrow may work ?

let object= base <== {a: 1, b: 2};

Does not overcome the grawlix objection.

Hmm, it's grawlix-y too but... how about

let object= base :: {a: 1, b: 2};

?

let object= base <== {a: 1, b: 2}; let object= base <: {a: 1, b: 2}; let object= base <| {a: 1, b: 2}; let object= base :: {a: 1, b: 2};

# Brendan Eich (12 years ago)

On Oct 31, 2011, at 10:04 AM, Jorge wrote:

On 31/10/2011, at 08:57, Brendan Eich wrote:

On Oct 31, 2011, at 12:20 AM, Jorge wrote:

Perhaps a long arrow may work ?

let object= base <== {a: 1, b: 2};

Does not overcome the grawlix objection.

Hmm, it's grawlix-y too but... how about

let object= base :: {a: 1, b: 2};

?

No, that's wanted for wiki.ecmascript.org/doku.php?id=strawman:guards -- precedent from Haskell and other languages, and the single-colon from ES4 doesn't mix well with object literals.

Grawlix is the general problem, not the solution.

# John J Barton (12 years ago)

On Mon, Oct 31, 2011 at 10:01 AM, Brendan Eich <brendan at mozilla.com> wrote:

On Oct 31, 2011, at 9:45 AM, John J Barton wrote:

In my opinion for new syntax to support classical inheritance should 1) target beginners and 2) help avoid the need for F.prototype/new F() pattern for simple inheritance.

John, I almost-completely agree with you (yay!), except for the |new F| objection. What's wrong with operator new for class instantiation?

I don't object to "operator new" for creating instances. (It is more wordy in definition than a function property "new", a minor point).

My objection is the specification of methods on the |.prototype| property of the right-hand side operand of "operator new". I understand that it makes some logical sense, but we also know that it's confusing to even experienced developers. We can't take it back. Can we make it's use less important? Can we avoid using this odd relationship in future features?

We could try to analyze why the F.prototype/new F() pattern is confusing. I think the pattern is confusing when you start where developers start. Given an object |E|, I want to create objects with the methods of |E| except from an override. My goals is: let f = new F(); // F is like E but different. So I must define F in terms of E.

In class languages I say: class F something E withOverrides {} In JavaScript I have to stop and think about |.prototype|. I want to concentrate on |E| and the overrides, but instead I am re-reading Crockford.

Immediately after this phase the class-based language pattern leads you to think you are accomplishing great things, but mostly you are focusing premature on abstraction details. But that critical phase from "given an object |E|" to declaring |F| provides a big advantage. I believe this is why devs gravitate to selfish and extends() models.

jjb

# Jorge (12 years ago)

On 31/10/2011, at 18:07, Brendan Eich wrote:

On Oct 31, 2011, at 10:04 AM, Jorge wrote:

Hmm, it's grawlix-y too but... how about

let object= base :: {a: 1, b: 2};

?

No, that's wanted for wiki.ecmascript.org/doku.php?id=strawman:guards -- precedent from Haskell and other languages, and the single-colon from ES4 doesn't mix well with object literals.

Grawlix is the general problem, not the solution.

Ok. I understand. And it's also going to be easier to find (its 'man' page :-) if it's a word, e.g.

google.com/search?q=beget+javascript, google.com/search?q=typeof+javascript, google.com/search?q=instanceof+javascript

than any grawlix-y term:

google.com/search?q=::+javascript, www.google.com/search?q==>+coffescript

So, fwiw, beget or begets sounds pretty good to me:

let object= base begets {a: 1, b: 2};

# Brendan Eich (12 years ago)

On Oct 31, 2011, at 10:45 AM, John J Barton wrote:

On Mon, Oct 31, 2011 at 10:01 AM, Brendan Eich <brendan at mozilla.com> wrote:

On Oct 31, 2011, at 9:45 AM, John J Barton wrote:

In my opinion for new syntax to support classical inheritance should 1) target beginners and 2) help avoid the need for F.prototype/new F() pattern for simple inheritance.

John, I almost-completely agree with you (yay!), except for the |new F| objection. What's wrong with operator new for class instantiation?

I don't object to "operator new" for creating instances.

Great.

(It is more wordy in definition than a function property "new", a minor point).

(Do you mean 'constructor' is a longer word than 'new'? Not sure what the parenthetical is getting at.)

My objection is the specification of methods on the |.prototype| property of the right-hand side operand of "operator new". I understand that it makes some logical sense,

It's how JS works, that's all. Agree it should be considered plumbing to be put behind a pretty cabinet door for n00b/classy programmers.

Immediately after this phase the class-based language pattern leads you to think you are accomplishing great things, but mostly you are focusing premature on abstraction details.

That seems like a problem in itself. Maybe we can't solve it, and we're better off adding classes. But I've seen that over and over too. It gives me pause about class as the best or one true way.

But that critical phase from "given an object |E|" to declaring |F| provides a big advantage.

Agreed.

I believe this is why devs gravitate to selfish and extends() models.

Or bounce off JS.

# David Flanagan (12 years ago)

I've been noodling around with various syntax ideas in this post, and it has gotten pretty long, so here are the highlights:

 var obj = base <| {a:1,b:2};   // I think its okay as-is.
 var obj = {:base> a:1, b:2};   // Its not really an operator, anyway
 var obj = base prototype {a:1,b:2}  // Prototype with pride!
 var obj = base share {a:1,b:2}  // JS: the friendly language
 var obj = with(base) {a:1, b:2}; // :-)

If any of these intrigue you, read on for my thoughts on why punctuation is okay in this case, and why I've proposed syntax that is not an operator.

I'm sympathetic to the anti-grawlix position. In this case, however, we're discussing an operator that is fundamental to the language and gets right to the heart of JavaScript's prototype system. The reason it is hard to name is that there is no precedent in other languages.
Because it is fundamental and unique to JavaScript, people will think of it as "that weirdly cool JavaScript operator". So, do we want them thinking "that weirdly cool operator that doesn't quite look like a triangle" or "that weirdly cool operator that sounds sort of biblical"?

I'm only sort of joking about that. My more serious point is that prototype-based inheritance is something that new programmers have to take some time to learn. Having to learn one new punctuation-based operator is really no extra effort, especially when it is such an important one. There have been previous proposals (I'm thinking of one for setting property attributes in object literals) that really did seem to increase the line-noise quotient of the language. But the triangle operator isn't one of those.

If the concern is just about the typography of <| not looking triangular enough, how about <*, where < shows the direction of the relationship and * says "this is really special and important" :-) Or, <-?

It is also worth thinking about the fact that <| is a very unusual operator because the RHS must be a literal. Like the . operator for property access which requires an identifier on the right, it could be considered a syntactic form that is not quite an operator. So could we put syntax before and after the proto object to make this an easier to understand concept? Like this:

 var obj = with(base) { a:1, b:2};

Redeeming with would be pretty cool, but I assume it would cause to much confusion to consider seriously. So what if the base object was between the | and the arrow:

 var obj = |base> {a:1, b:2};

I know that changes the direction of the arrow around, but I suspect that pointing at the derived object is actually more intuitive for most programmers, anyway. I don't know if this syntax works in the grammar, and it looks a little phallic (the "rocket" operator ;-), but to my eye, it helps to convey what is going on better than a simple infix operator.

Or, to emphasize that this new syntactic form is all about specifying a prototype for an object (or array, function, or regexp) how about forcing it all to be within curly braces?

 var obj = {:base> a:1, b:2};
 var arr = {:base> [a,b,c]};
 var func = {:base> function(...args) {...}};
 var re = {:base> /pattern/g};

(I'm using a colon here instead of the vertical bar because I'm still hoping for block lambdas...)

Setting a prototype on an array object is an unusual enough thing to do that I think it can certainly justify the wrapping and even extra indentation that comes with putting [] inside {}.

If its got to be an infix keyword operator, I'm not crazy about "beget". I'd prefer "proto". And actually, I'd even prefer to type the extra 4 characters and use "prototype" because it is a verb. JavaScript has prototype based inheritance, so let's wear that proudly and make it a keyword operator.

The next best I can come up with is "share". (That is assuming that "sub" and "subclass" are off-limits because ES.next.next may someday have a "class" keyword.)

If the left and right-hand sides of the operator were swapped, it would be easy to name the operator: "inherit" would be an obvious choice. We need the inverse of "inherit", something like "designate an heir", but I don't think English has a word with that meaning. The word "heir" itself is nice and short, but I assume that the fact that it is not a verb disqualifies it.

So if we can't find a good keyword using the inheritance-by-children-upon-death-of-the-parents metaphor, we can go for parent/child metaphors, which is where beget comes from. And from biology we can go back to inheritance in the form of genetic inheritance. If the prototype object is like DNA (and its properties are genes) is there a verb we can draw from genetics to describe what the operator does?

Or, can we just break away from the family tree/inheritance metaphor entirely and just say what the operator does? That's where my "share" suggestion comes from: the prototype object shares its properties with the derived object.

# Allen Wirfs-Brock (12 years ago)

thanks, Dave, some lateral thinking is really helpful. more below

On Oct 31, 2011, at 12:43 PM, David Flanagan wrote:

I've been noodling around with various syntax ideas in this post, and it has gotten pretty long, so here are the highlights:

var obj = base <| {a:1,b:2}; // I think its okay as-is. var obj = {:base> a:1, b:2}; // Its not really an operator, anyway var obj = base prototype {a:1,b:2} // Prototype with pride! var obj = base share {a:1,b:2} // JS: the friendly language var obj = with(base) {a:1, b:2}; // :-)

what do you think of <: instead of <| ?

...

eem to increase the line-noise quotient of the language. But the triangle operator isn't one of those.

If the concern is just about the typography of <| not looking triangular enough, how about <*, where < shows the direction of the relationship and * says "this is really special and important" :-) Or, <-?

if ( a<-5) ...

It is also worth thinking about the fact that <| is a very unusual operator because the RHS must be a literal. Like the . operator for property access which requires an identifier on the right, it could be considered a syntactic form that is not quite an operator.

yes, that is what it is.

... Or, to emphasize that this new syntactic form is all about specifying a prototype for an object (or array, function, or regexp) how about forcing it all to be within curly braces?

var obj = {:base> a:1, b:2}; var arr = {:base> [a,b,c]}; var func = {:base> function(...args) {...}}; var re = {:base> /pattern/g};

(I'm using a colon here instead of the vertical bar because I'm still hoping for block lambdas...)

interesting idea, an universal object literal form...

We should experiment with what it looks like when base is a more complex expression.

Setting a prototype on an array object is an unusual enough thing to do that I think it can certainly justify the wrapping and even extra indentation that comes with putting [] inside {}.

If its got to be an infix keyword operator, I'm not crazy about "beget". I'd prefer "proto". And actually, I'd even prefer to type the extra 4 characters and use "prototype" because it is a verb. JavaScript has prototype based inheritance, so let's wear that proudly and make it a keyword operator.

The next best I can come up with is "share". (That is assuming that "sub" and "subclass" are off-limits because ES.next.next may someday have a "class" keyword.)

If the left and right-hand sides of the operator were swapped, it would be easy to name the operator: "inherit" would be an obvious choice. We need the inverse of "inherit", something like "designate an heir", but I don't think English has a word with that meaning. The word "heir" itself is nice and short, but I assume that the fact that it is not a verb disqualifies it.

"bequest"

# Axel Rauschmayer (12 years ago)

If its got to be an infix keyword operator, I'm not crazy about "beget". I'd prefer "proto".

+2

The next best I can come up with is "share". (That is assuming that "sub" and "subclass" are off-limits because ES.next.next may someday have a "class" keyword.)

+1

If the left and right-hand sides of the operator were swapped, it would be easy to name the operator: "inherit" would be an obvious choice. We need the inverse of "inherit", something like "designate an heir", but I don't think English has a word with that meaning. The word "heir" itself is nice and short, but I assume that the fact that it is not a verb disqualifies it.

German has a word for it, my dictionary says the translation is “bequeath”.

# Allen Wirfs-Brock (12 years ago)

On Oct 31, 2011, at 10:45 AM, John J Barton wrote:

On Mon, Oct 31, 2011 at 10:01 AM, Brendan Eich <brendan at mozilla.com> wrote:

On Oct 31, 2011, at 9:45 AM, John J Barton wrote:

In my opinion for new syntax to support classical inheritance should 1) target beginners and 2) help avoid the need for F.prototype/new F() pattern for simple inheritance.

John, I almost-completely agree with you (yay!), except for the |new F| objection. What's wrong with operator new for class instantiation? ... In class languages I say: class F something E withOverrides {} ...

Immediately after this phase the class-based language pattern leads you to think you are accomplishing great things, but mostly you are focusing premature on abstraction details. But that critical phase from "given an object |E|" to declaring |F| provides a big advantage. I believe this is why devs gravitate to selfish and extends() models.

John,

I'm going to circle back to some of your other points in another message, but first I want to address your final point.

You start in the 9:45 AM message talking about making classical inheritance simple. However, in the final sentence you mention selfish and extends() as the things that devs gravitate towards as a solution to that problem. But those are both (more or less) prototypal inheritance based designs. They aren't doing classical inheritance.

We have talked quite a bit about how we could support very simple expression of prototypal inheritance that is very close to the ideal you seem to be looking for:

let E = {...} //E is just some object

let F = E <| { //bikesheding <| is a separate topic method1() {}, method2() {}, //etc. };

var f = new F;

but if you want to have instance initialization behavior you would define it like:

let F2 = E <| { method1() {}, method2() {}, //overrides constructor(init) { this.x = init; } };

var f2 = new F2(42);

We have recently taken to calling this pattern "object exemplars". It is prototypal inheritance, almost exactly equivalent to what selfish does. If we could all be satisfied with this there would be no need for the ongoing debate.

However, some people do not seem to be satisfied.

Fundamentally, what we are trying to enable here is the simple creation of named abstractions over sets of behaviorally related objects. This is important became it allows devs to think and communicate about the set rather than the individual objects. The complication comes when we must decide what sort of runtime entity is actually assigned a name. In selfish and in the above examples it is a regular object that is named. This object is considered to be a "prototype" because it provides the prototypical behavior that is shared by all members of the abstraction. This is what is going on in my above examples even though the word "prototype" never explicitly appears.

The objection that is raised is that we are assigning the name to the wrong kind of object. The original JavaScript approach to creating objects uses a separately defined constructor function and it is the function that is given a name. When you say new Array() in JS you are not referring to the prototypal array object, instead you are referring to a function that creates arrays and implicitly associates they with Array.prototype. Some would go as far to say that named constructor functions are how JS manifests classes -- the constructor functions are the class objects. Their objection to the object exemplar pattern is that it isn't really how JS does classes.

Sometimes it sounds like what you are asking for is precisely what objects exemplars provide. But other times you say you want "classical inheritance". Which is it?

# John J Barton (12 years ago)

On Mon, Oct 31, 2011 at 4:27 PM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:

On Oct 31, 2011, at 10:45 AM, John J Barton wrote:

On Mon, Oct 31, 2011 at 10:01 AM, Brendan Eich <brendan at mozilla.com> wrote:

On Oct 31, 2011, at 9:45 AM, John J Barton wrote:

In my opinion for new syntax to support classical inheritance should 1) target beginners and 2) help avoid the need for F.prototype/new F() pattern for simple inheritance.

John, I almost-completely agree with you (yay!), except for the |new F| objection. What's wrong with operator new for class instantiation?

...

In class languages I say:

class F something E withOverrides {}

...

Immediately after this phase the class-based language pattern leads you to think you are accomplishing great things, but mostly you are focusing premature on abstraction details. But that critical phase from "given an object |E|" to declaring |F| provides a big advantage. I believe this is why devs gravitate to selfish and extends() models.

John, I'm going to circle back to some of your other points in another message, but first I want to address your final point. You start in the 9:45 AM message talking about making classical inheritance simple.  However, in the final sentence you mention selfish and extends() as the things that devs gravitate towards as a solution to that problem.  But those are both (more or less) prototypal inheritance based designs.  They aren't doing classical inheritance.

I guess you think I am being inconsistent, in asking for classical then pointing to prototypical examples. There is a bit of truth to your claim. Before your explanations on this thread I knew that classes were vague inferior to prototypes, mainly because I wrote too many and yet not enough singleton classes in Java. Now I have deeper understanding of classes (and a lower opinion of classes). But the only aspect of my opinion on classes that matters is that we need a simple pattern for classes. I keep coming back to 'selfish' because it provides a 'simple' solution to prototypical inheritance.

I don't think devs are trying to solve the "I want to do classical inheritance" problem. Rather they are trying to write an app that makes sense. From this point of view a confusing pattern for classical inheritance won't be useful. The thread-intro proposal is in my opinion confusing and I am citing as evidence our experience with "new F()/F.prototype".

We have talked quite a bit about how we could support very simple expression of prototypal inheritance... We have recently taken to calling this pattern "object exemplars". It is prototypal inheritance, almost exactly equivalent to what selfish does. If we could all be satisfied with this there would be no need for the ongoing debate.

I could be satisfied, but I know you are not satisfied since you have offered the pattern at the top of the thread. ...

Sometimes it sounds like what you are asking for is precisely what objects exemplars provide.  But other times you say you want "classical inheritance".  Which is it?

This thread is about your interesting and provocative model for classical inheritance in the mode of JavaScript. I'm not advocating for classical inheritance. Rather, I'm advocating for 'simple classical inheritance' and if we can't have simple, let's not have classical.

What I don't want is a "classical" inheritance syntax that perpetuates the confusing "new F()/F.prototype" paradigm and also seems more complex than a Java-like solution.

jjb

# Allen Wirfs-Brock (12 years ago)

On Oct 31, 2011, at 7:37 PM, John J Barton wrote:

On Mon, Oct 31, 2011 at 4:27 PM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:

We have talked quite a bit about how we could support very simple expression of prototypal inheritance... We have recently taken to calling this pattern "object exemplars". It is prototypal inheritance, almost exactly equivalent to what selfish does. If we could all be satisfied with this there would be no need for the ongoing debate.

I could be satisfied, but I know you are not satisfied since you have offered the pattern at the top of the thread. ...

Actually, I would be quite satisfied with object exemplars as the primary pattern for defining named abstractions over objects. The class pattern at the head of the thread is put forward in a attempt to satisfy those who are insisting on a class definition construct that fully supports all of the really complex features of class abstractions that show up in other class-based dynamic object-oriented languages (and additional new requirements) and also fully supports the class pattern that is implicit in the ES built-ins. What I am trying to show that those requirements could be satisfied based upon a compositional pattern using just <| and .{ . My belief that such a compositional solution is adequate and better than trying to define a very complex class semantics that may prove to be defective in the long run.

Sometimes it sounds like what you are asking for is precisely what objects exemplars provide. But other times you say you want "classical inheritance". Which is it?

This thread is about your interesting and provocative model for classical inheritance in the mode of JavaScript. I'm not advocating for classical inheritance. Rather, I'm advocating for 'simple classical inheritance' and if we can't have simple, let's not have classical.

It actually sounds like you are advocating for prototypal inheritance that is as simple to use as simple uses of classical inheritance in some languages. I totally agree.

What I don't want is a "classical" inheritance syntax that perpetuates the confusing "new F()/F.prototype" paradigm and also seems more complex than a Java-like solution.

I agree. Except that I am fine with expert using those technique if them find them appropriate and also having them available to framework and transpiler authors.