How much sugar do classes need?

Peter Michaux petermichaux at gmail.com
Sat Nov 22 20:54:29 PST 2008


2008/11/22 Mark S. Miller <erights at google.com>:

>     // before desugaring
>     class Point(x, y) {

Having arguments makes this entire example seem like a function. That
is ok, perhaps good even, but some of the code inside the class block
does not seem like it will execute as though the class is a function
call or even close. The static code seems out of place.

>       static {

It isn't clear that static members is a must. But if they are...

>         let privClassVar = 1;
>         const privClassConst = -1;

So members are private by default? I like that and it is consistent
with a style of JavaScript OOP popular today. In the wiki page members
are public by default which is as dangerous as implied globals (i.e. a
missing "var") in ES3.

>         Point.pubClassConst = -3;

Why not the following?

 public pubClassConst = -3

>       }

In Java a static block runs when the class is first loaded. Is that
the case here? I think the ability to initialize the class is
important if some setup needs to be done to establish the class
members.

For declaring class variables, I prefer the static modifier in the wiki page

  static let privClassVar = 1;


>       let privInstVar = 2;
>       const privInstConst = -2;

Does "const" have "let" scoping?


>       public self implements Point {
>         to toString() {
>           return '<' + self.getX() + ',' + self.getY() + '>';
>         },
>         to getX() { return x; },
>         to getY() { return y; }

What do the "to" modifiers do?

>         let pubInstVar: 4,
>         const pubInstConst: -4
>       };

I'm not really a fan of this section, in general. I prefer the syntax
similar to the wiki page

  public function toString() {
  	return '<' + self.getX() + ',' + self.getY() + '>';
  };
  public const pubInstConst = -4;

>       return self;

Why the explicit need to return "self"? That doesn't seem very
"sweet". It seems like boilerplate.

>     }

------

The wiki page shows a "private" keyword. It seems to me, there is no
need for a "private" keyword at all to get instance private. I think
instance private is the good kind of private. As shown in your
example, the following can be instance private.

class Point(x, y) {
  var instPrivVar = 1;
}

If class private is desired, which I don't think it is, then I think
some other modifier should be introduced (i.e. not "private" as
"private" should me totally "private".)

There is no inheritance here and so Java's "protected" doesn't seem to
be an issue.

---------------

Leaving class members out of the picture makes the whole issue much
clearer. I was thinking and kind of had the impression we might be
headed to writing something like the following

class Point(x1, y1) {

  var privInstVar = 2;
  const privInstConst = -2;

  // code that needs to run at construction time
  // is interspersed anywhere inside the class block
  var foo = 3 * x + y;

  function privFn(a) foo + a;

  public function toString() {
    return '<' + x1 + ',' + y1 + '>';
  };
  public get x = function() x1;
  public get y = function() y1;
  public var pubInstVar = 4;
  public const pubInstConst = -4;

}

The above would desugar to the same style of how some programmers are
writing JavaScript code today. I write code roughly like that and
would write code just like it if I could. I think many JavaScript
programmers would take only a few minutes to learn how to write code
like my example above...and many would breath a big sigh of relief.

Added benefits of the sugar are auto-freeze (allowing type checking as
you noted) and compiler/interpreter optimizations.

I used "var" instead of "let" in my example. I don't know any
advantage of "let" here.

----

If there are ever going to be multi-methods (perhaps dispatching on
type or other properties), then the examples we have both shown seem
inappropriate as there can only be one constructor. In this case it
might be beneficial/necessary to go more to the Java-style

class Point {

  var privInstVar = 2;
  const privInstConst = -2;
  var x1, y1;
  var foo;

  function Point(x:int, y:int) {
    // no "public" in constructor as slots allocated
    // at compile time and different constructors
    // shouldn't add different public properties
    x1 = x;
    y1 = y;
    // construction-time code must be in a constructor
    foo = 3 * x + y;
  }

  function privFn(a) foo + a;

  public function toString() {
    return '<' + x1 + ',' + y1 + '>';
  };
  public get x = function() x1;
  public get y = function() y1;
  public var pubInstVar = 4;
  public const pubInstConst = -4;

}

That is pretty darn Java-ish but the class syntax part of Java is not
the problem with that language. The other parts are. ;-)

---------------

Another thing I noticed in the wiki page is a possible syntax for members

  public x;
  public bar() {}

This makes "public <identifier>" short for "public var <identifier>"
and, more importantly,
makes "public <identifier>()" short for "public function <identifier>()"

If that is going to exist, and that means "function", not "lambda" (if
lambda makes it into the language), then why not the following for a
function definition?

  var bar() {}

If "var bar() {}" is not allowed then I don't see why "public bar()
{}" would be allowed. I don't think class sugar should make the
language more asymmetrical as asymmetry makes a language difficult to
learn and understand. Symmetry makes a consistent, predictable
language. Symmetry equals success in nature for a reason.

Peter


More information about the Es-discuss mailing list