How much sugar do classes need?

Peter Michaux petermichaux at gmail.com
Sat Nov 29 23:20:27 PST 2008


On Sat, Nov 29, 2008 at 9:49 PM, Mark S. Miller <erights at google.com> wrote:

[1,2,3) Integrity]

It seems more integrity is desired. Programmers can use ES3 with
discipline but it seems folks don't trust other folks or that "the
junior programmer" will exercise the right amount of discipline.
Programmers won't just stick to the documented API and won't just
leave other people's objects alone. It is unfortunate. As far as I
know, Gmail was written using only underscore naming convention for
privacy so discipline can work.

> 4) Minimize new kernel semantics: As demonstrated by various proposed
> desugarings, ES3.1 already contains adequate mechanism for the kinds of high
> integrity programming people expect from ES-H classes. Ideally then, classes
> would add no new kernel semantics at all to ES-H, but merely desugar to
> other elements already present. (The one exception we will probably make is
> more direct support for nominal types and type constrained variables and
> properties.)

ES3 did not expose enough control to the programmer so that he could
write the desugared version of a class. ES3.1 has exposed more with
things like Object.freeze. Perhaps more pieces may need to be exposed.
I realize this is different than adding new kernel semantics but I
think it is worth noting the difference.

I don't like the idea that types and type checking are being or might
be conflated with classes. Nominal type checking systems, casting, and
general fighting with the compiler to get otherwise valid code to work
is a nightmare. These things make writing code harder and more
painful. I am vary wary of type checking and if such a system makes it
into ES, when I have to deal with third party code that uses type
checking poorly, I sure a part of my soul will die. "Optional" type
checking won't actually be optional. Its impact *will* be endured when
dealing with code that uses type checks.

> 3) Avoid accident prone constructs: Moderate. On the positive side, because
> self is simply a lexically captured variable, extracted methods are already
> bound to their instance without any new mechanism. Because they do not
> mention 'this', little damage arises if a function/method/constructor is
> invoked as a constructor/function/method, etc. OTOH, All five properties are
> enumerable though probably only the two data members should be.

I like the use of "self" in this example and it makes for easier
programming. Any of the methods could be used as an event handler
without worrying about dynamically bound "this". Surely this is a
major hump for all programmers who start with JavaScript and want to
write

  setTimeout(obj.foo, 100);

and the "foo" method uses "this".

I also posted an example to this list about creating observable
objects which benefit from not using "this".

https://mail.mozilla.org/pipermail/es-discuss/2008-August/007197.html

[In a follow-up, I noted how there were an bad set of parens after
"fire" in one place.]

Avoiding "this" is a major benefit, in my opinion.

> 4) Minimize new kernel semantics: Perfect.
>
> 5) Syntax as user interface: Good. I would have given this one a "Perfect"
> but for your point about access public members from inside as simple
> variable accesses. Obviously, one could instead write
>
>   function getX() { return privX; }
>   const self = {
>     ...
>     getX: getX,
>     ...
>
> but this isn't perfect either. I'll come back to this in the next email.

I agree, this is not good "syntax as user interface". This is what I
was addressing in my longer desugared code where "self" is aggregated
automatically when "public" is written.

>> If making a public method means explicitly
>> adding a property to an object then your proposed sugar is only
>> nutrasweet ;-) I mean that jokingly. I understand you are trying to
>> make a minimal proposal to see how minimal it can be.
>
> Indeed. A sweet syntax that doesn't cause the growth of fat! ;)

Yeah, but that aftertaste!

> I am not attached to the specifics of my "object"/"public" block. But what
> this thread has already taught me is that it is instances that need sugar,
> not classes. Enhancing the object literal notation is one way to get there.

That is interesting. I think the general feeling was that constructors
were what needed the sugar. The fact that there are several ways to
create objects in ES causes a bit of a problem here. I'll definitely
think on this. Perhaps both object literals need more expressive
powers and constructors need sugaring.

----

I think that my example covers the points you are making except for
the "self" issue which has a reasonable easy boiler-plate-like fix.

When calling "new Point(1, 2)", it seems very consistent with ES that
there will be a "this" object in the Point constructor (i.e. function
or sugared class.) If the programmer wants a lexically bound "self"
then one line at the beginning of the class will take care of that.

  class Point(privX, privY) {
      var self = this;
      let privInstVar = 2;
      const privInstConst = -2;
      public toString() '<' + x() + ',' + y() + '>';
      public get x() privX;
      public get y() privY;
      public pubInstVar = 4;
      public const pubInstConst = -4;
  }

This allows the toString line to be written as

    public toString() '<' + x() + ',' + y() + '>';

or

    public toString() '<' + self.x + ',' + self.y + '>';

The issue about a dynamically bound "this" or a lexically bound "self"
is only an issue in this case if a method is "borrowed" like in the
setTimeout example above. That is, a method called without it being a
message passed to the receiver object. With the "var self=this;" line,
a designer of a class would be able to choose how method borrowing
will work. No I don't think this "this"/"self" solution is ideal but I
don't think it is awful either given how "this" is used in ES now.

Peter


More information about the Es-discuss mailing list