Finding a "safety syntax" for classes

Russell Leggett russell.leggett at gmail.com
Tue Mar 20 11:51:45 PDT 2012


>
>
>>    * has a declaration form that uses the class keyword and an
>>
>>      identifier to create the class
>>
> Why to rule out other possibilities (though I understand this one is the
> "least surprise" one)?
>

I'm not sure I understand what you are asking, but I think you answered
your own question. Remember - *safety syntax*. Minimal syntax without
limiting future possibilities. We know that we will need "class Foo {".
Let's just accept that as the base with future options later. And by later
I mean "it can still be changed for ES6, just not for this discussion".


> A few things that are different from CoffeeScript:
>>
>>    * if there is no constructor, it doesn’t automatically pass
>>
>>      arguments up to the parent constructor. I think that would be nice
>>      but more controversial.
>>
> A thing for discussion. Clear is clear, but you define the constructor
> anyway (you have to, it's the JS way). Maybe there should be extends* to
> say 'auto-generate forwarding, not clear one'.
> Though this is not the part of "safety" plan.
>

We would have to decide what happens if they don't supply a constructor. I
think we would need a default, and in my mind there are 3 possibilities:

   1. Empty constructor - does nothing.
   2. Calls super with no args
   3. Calls super as a pass through

I'm fond of 3, but might be missing some controversial reason for one of
the others. Personally, I would be willing to take any of them for the sake
of classes.


>     * to call super on a method you have to indicate the method super.move
>>    * while not obvious in the example, I would say the class body should
>>          o be its own construct, not just an object literal - this
>>
> -1. See more below.
>
>             makes it easier to have methods without ,’s and be
>>            future-proof for whatever we might want later
>>
> I have a lot of reasons (gut instinct, too, but also some though
> experiments on how things get powerful and concise things can be if classes
> automaticall had all the possibilities of (potientially revved-up) object
> literals [1]).
> So I need to see a really strong argument for abandoning the cause of
> "body of class should be the same as the body of object literal (with
> possible little numbers of changes)".
>

Ok, lets put it this way - my safety syntax only allows constructor +
methods, with no commas in between. If commas after methods can be elided
in object literal extensions then we're still on solid ground, it could go
either way. What I would argue, though, is that we don't define the class
body as equivalent to an object literal, there is still too much
controversy there.


>
> So my -1 holds if you want to add anything that goes beyond the
> object-literal syntax, and I'd give -0.66 in case where you would restrict
> it too much.
>
> If you restrict it to only hold constructor and methods, it is still a
> compatible (though stripped) object-literal - you can have methods there
> (constructor is nothing special, just a method named 'constructor'; the
> magic of class keyword grants it [[Construct]] and .prototype created from
> {} block and according to object literal syntax you can have methods there
> without comma), so this would be -0.66.
>

Well then I guess its a -0.66 from you, but remember this is the *safety
syntax*! The battle can rage on later.


>
> Without this restriction it would more or less be the same as proposal
> "3." in the thread unhappily named 'u' (my mail client probably did
> something wrong):
>
> 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 { // no problem if here is 'extends', but
>                      // I'd like it for function declaration, too, then
>                      // as in thread "extends with functions"
>  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
>
>
>
> I silently assume here that extends creates, of course, double chain
> (constuctor inherits as well as prototype inherits, not just the latter)
>

Correct


>
>           o only allow a constructor function and methods - nothing
>>
>>            else. No public/private fields. No worrying about var x =
>>
> private can be done as above - out of class - it does not need as part of
> its syntax


Absolutely


>
>             {a:b} inside the class body – if it should be allowed, what
>>            the syntax should be etc. With the "safety syntax", less is
>>            more as long as it gets accepted.
>>
>> So what do you say people? Is it safe enough? One of the biggest
>> arguments I’ve heard against rushing in a class syntax now is that once
>> its in we have to keep supporting it. I say that this is small enough we
>> won’t regret it, and makes it possible to do a lot more in the future.
>>
> It's too small. Whenever I want a shared field in prototype (other than
> method), I still must
>
> MyClass.prototype.{
>  sharedBar: 0,
>  sharedBaz: ""
> };
>
> This makes its inclusion a bit questionable (same for statics).
>

If the alternative is *no* class syntax, you will have to do this anyway.
Isn't this proposal still better than nothing?


>
> Yes, we can go in little steps... but lots of them we already have (super
> expressions are already planned to be orthogonal to classes), and I think
> the next small step should be 'extends' for function declarations (which,
> unless <|, explicitly says "I am creating double chain here, in the spirit
> of 'classical' class inheritance; and if thing after extends is not
> constructor, I throw").


What would you rather have?

    function Snake(name) extends Animal {
        super(name);
    }.prototype.{
        move(){
            alert("Slithering...");
            super.move(5);
        }
    }

or

    class Snake extends Animal {
        constructor(name){
            super(name);
        }

        move(){
            alert("Slithering...");
            super.move(5);
        }
    }

I know which one I would pick. At least as a safety syntax. The arguing can
continue after that. I hope we get more than this minimum, but please,
don't the indecision make the choice be "nothing".

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


More information about the es-discuss mailing list