u

Herby Vojčík herby at mailbox.sk
Thu Mar 15 11:21:12 PDT 2012


Brendan Eich wrote:
> Definitely, but classes have bigger issues than private syntax, and have
> for a while. Class-side inheritance, body syntax, whether there should
> be any declarative public syntax, what nested classes mean, static or
> 'class' members -- that's a partial list from memory.
>
> Minimal classes based on object literals could be done but seem too
> minimal. As Waldemar suggested and Allen has worked to develop, they
> tend to collapse into object literals (with smaller extensions).

I am interested in this. Do you believe such classes, which are based on 
object literal syntax are too minimal? There is lots of possibilities 
what syntax to choose. And, classes in JS are in fact just an object (a 
prototype) which can be described (or extended) by a literal(-extension) 
(plus a constructor, yes, but it is just a little decoration to it).

I'd like to know what these solutions lack (why are they "too minimal"). 
I will sketch some of them (they will use existing features, like super 
expressions, <|, private name shortcut declaration; some of the features 
more liberally).

=====

1. 'class ...}' as a sugar for 'function ...}.prototype':
(liberal use of <| for (sugared) function declarations as well)

private arr;

class List (n) {
   this. at arr = n === +n ? new Array(n) : [];
}.{
   at (i) {
     i = +i;
     if (i>=0 && i<this. at arr.length) { return this. at arr[i]; }
     else throw "Out of bounds: "+i;
   }
   size () { return this. at arr.length; }
}

List.{
   from (array) {
     var r = new this();
     r. at arr = array;
     return r;
   }
};

private writeArr, readOffset;

List <| class Queue () {
   super();
   this. at writeArr = [];
   this. at readOffset = 0;
}.{
   at (i) { /* needs redefinition */ }
   size () {
     return super.size() - this. at readOffset + this. at writeArr.length;
   }
   push (elements) {
     return writeArr.push.apply(writeArr, elements);
   }
   shift () {
     //reads from arr; shifts []->writeArr->arr if empty
   }
}

// Queue inherits from, needs no Queue.{...} if does not want something 
additional

Cons: class expression would not return the class
Pros: integrated to the language, just a pure helper sugar

=====

2. 'class expr [{...}] [static {...}]' as a sugar for '(expr).prototype
[.{...}] [.constructor.{...}] but always returning the constructor':
(liberal use of <| for function declarations as well)

private arr;

function List (n) {
   this. at arr = n === +n ? new Array(n) : [];
}

class List {
   at (i) {
     i = +i;
     if (i>=0 && i<this. at arr.length) { return this. at arr[i]; }
     else throw "List: Out of bounds: "+i;
   }
   size () { return this. at arr.length; }
} static {
   from (array) {
     var r = new this();
     r. at arr = array;
     return r;
   }
};

private writeArr, readOffset;

List <| function Queue () {
   super();
   this. at writeArr = [];
   this. at readOffset = 0;
}

class Queue {
   at (i) { /* needs redefinition */ }
   size () {
     return super.size() - this. at readOffset + this. at writeArr.length;
   }
   push (elements) {
     return writeArr.push.apply(writeArr, elements);
   }
   shift () {
     //reads from arr; shifts []->writeArr->arr if empty
   }
}

// Queue inherits from, needs no static if it does not want something
additional

Cons: Two pieces
Pros: You can define "partial classes" which have their pieces defined 
at different places in code.

=====

3. 'class Name {...} [static {...}]' as a quasi-sugar for 'Name.prototype
.{...} [.constructor.{...}] with Name body derived from constructor
method in first {...}; always returning the constructor':
(liberal use of <| for class declarations as well)

private arr;

class List {
   constuctor (n) {
     this. at arr = n === +n ? new Array(n) : [];
   }
   at (i) {
     i = +i;
     if (i>=0 && i<this. at arr.length) { return this. at arr[i]; }
     else throw "Out of bounds: "+i;
   }
   size () { return this. at arr.length; }
} static {
   from (array) {
     var r = new this();
     r. at arr = array;
     return r;
   }
};

private writeArr, readOffset;

List <| class Queue {
   constructor () {
     super();
     this. at writeArr = [];
     this. at readOffset = 0;
   }
   at (i) { /* needs redefinition */ }
   size () {
     return super.size() - this. at readOffset + this. at writeArr.length;
   }
   push (elements) {
     return writeArr.push.apply(writeArr, elements);
   }
   shift () {
     //reads from arr; shifts []->writeArr->arr if empty
   }
}

// Queue inherits from, needs no static if it does not want something
additional

Pros: One-piece
Cons: Maybe slightly magical for the hardcore (constructor)

=====

Again, what is weakness of these solution that there must be something 
heavier?

> /be

Thanks, Herby


More information about the es-discuss mailing list