On 28.03.2011 0:05, Brendan Eich wrote:
On Mar 27, 2011, at 11:33 AM, Juan Ignacio Dopazo wrote:

On Sat, Mar 26, 2011 at 6:31 PM, Dmitry A. Soshnikov <[email protected] <mailto:[email protected]>> wrote:

    Why not just to use already reserved `extends` keyword for
    specifying a superclass? These XML-like braces looks not so elegant.


I asked this question a couple of days ago. The answer is quite simple. Object initializer extensions are more than just constructor syntax. They allow you to create complex objects without all the hassle in (function(){}()). So the constructor syntax was made this way to be consistent with object initializer syntax.

The meta syntax (e.g., var obj = {<proto: p>, key: val}) is not inconsistent with initialisers, it's an extension to them. But it's not the only self-consistent extension. Dmitry mentioned letting the meta properties appear to be regular key: value pairs but distinguishing the keys with @ or #.

Allen makes the point that class D extends B {...} may look too much like languages where it means something quite different. That's true, but I am not sure JS should be so special that it seems to mix bits of those languages into one (of several conceivable) extensions to initialiser syntax:

class D {<superclass B>};

Whatever you think of the meta section, the leading 'class D {' telegraphs influence from, and just familiarity with, those other languages. And I don't think that is a bad thing even if semantics differ.

Just changing 'class' to 'constructor' (adding a new perhaps-only-contextually reserved word, and a long one at that) is not the issue. Sure, doing that would in a text-only way make the syntax not look like any other language, exactly. But ignore the skin: the bones look familiar, going back to C structs.

Now add some notion of inheritance and you're following the C++ "body plan".


Exactly. "Classes" are not about just the "class" keyword, but about the _ability to classify_, i.e. to program in classified (i.e. with object-patterned programming). JS supports (and supported all these years both approaches: delegation-based prototypal (i.e. unclassified or chaotic code reuse) and classical (classified or systematized code reuse).

Thus, a "class" in JS is a pair of "constructor function + prototype". From this viewpoint, e.g. classes in Python (or CoffeeScript) are just syntactic sugar of the same delegation-based inheritance used in JS. And this means that JS also may have this sugar -- to allow users to program in classified manner (if they need to). So there's no a big difference between these languages and therefore keyword `extends` may fit absolutely normally.

Here how I see classes syntactic in JS (a combination of Coffee's sugar + Java's syntax, since we can't eliminate it).

Notes:

I think that usage of thing like: class method fromString() { .. } are to verbose.
Don't think we need another keyword `method` at all.

Also I used a syntactic sugar for `this` keyword as `@`. This `at` allows easily to define and distinguish class- and instance- methods. The rule is simple: if a property/method inside the class body starts with @ -- it's the class's property/method (i.e. `this` refers to class). In other case -- it's an instance method. @ evaluated inside the instance method refers of course to the instance.

Here's a small example with sugared (on the left hand) and desugared (on the right hand side) views: http://bit.ly/hvS7hl Take a look please.

And below is just an example without the desugaring. Thus, the definiton itself is in declarative form. Also I think it's good to provide both dynamic and static classes. By default I used dynamic classes, so `static` keyword is explicit.

In the example I also used `include` keyword as an ability to mixin some module as a direct ancestor of an instance, i.e. before the class in the hierarchy. Mixins/traits will allow to reuse the code horizontally (not only with a single vertical inheritance "tower").

/* ------------------------------------------------------
 * Class Point definition
 * ------------------------------------------------------
 */

class Point {

    /**
     * Class method (placed on constructor function)
     */
    @fromString: function (s) {
        return new Point(parse(s));
    }

    /**
     * Instance intializer (aka "constructor")
     */
    initialize: function (x, y) {
        @move(x, y);
    }

    /**
     * Simple instance method (placed on prototype)
     */
    move: function (x, y) {
        @x = x;
        @y = y;
        @repaint();
    }

    /**
     * Class property (placed on constructor function)
     */
    @x: 10
}

/* ------------------------------------------------------
 * Class Point3D definition
 * ------------------------------------------------------
 */

static class Point3D extends Point {

    include Comparable;

    /**
     * Class static property
     */
    @instances: []

    /**
     * Instance intializer (aka "constructor")
     */
    initialize: function (x, y, z) {
        super(x, y);
        @z = z;
        @class.instances.push(@); // save the instance
    }
}

/* ------------------------------------------------------
 * Examples:
 * ------------------------------------------------------
 */

// create new 3D point
let point = new 3DPoint(10, 20, 30);

console.log(point); // "[instance 0x1382 of Point3D class]"

// inherited method

point.move(100, 200);

// introspect the class

console.log(point.class); // "[class Point3D]"
console.log(point.class === Point3D); // true

// instrospect the super class

console.log(point.class.super); // "[class Point]"
console.log(point.class.super === Point); // true
console.log(Point3D.super === Point); // true

console.log(point instanceof Point3D); // true
console.log(point instanceof Point); // true

// class method

let p = Point.fromString("10-20");
console.log(p.class); // "[class Point]"

// analyze class methods and properties
console.log(Point.classMethods); // ["fromString"]
console.log(Point.classProperties); // ["x"]
console.log(Point.instanceMethods); // ["move"]

console.log(Point3D.classProperties); // ["instances"]


How does it look like? Do we need such a sugar? For both -- classes and `this` as `@`? Then # can be used for meta-properties on initialisers.

Dmitry.


Do we really need to look different yet still have bones that look so familiar? I am not convinced.

The strongest case for extending initialiser syntax is that it is "nearly declarative" today. That suggests strongly making the extension fully declarative, i.e., not usable as an expression. And that, all else equal (never is, but:) says to consider class D extends B {...}. My 2 cents.

/be


_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to