I noted some open issues on "Classes with Trait Composition"

classic Classic list List threaded Threaded
78 messages Options
1234
Reply | Threaded
Open this post in threaded view
|

Re: I noted some open issues on "Classes with Trait Composition"

Brendan Eich-3
On May 19, 2011, at 4:24 PM, Mark S. Miller wrote:

http://wiki.ecmascript.org/doku.php?id=strawman:classes_with_trait_composition#member_declarations_and_definitions is light on details, but I took these to define local bindings usable in other ClassElements -- not to create prototype properties (or any kind of property on an object).

Did I miss something?

Yes. An unannotated Declaration defines a prototype property of that name. 

    class Point {
      const x = 0;
      //...
    }

defines a non-writable, enumerable, non-configurable "x" property on Point.prototype, as if by

    Object.defineProperty(Point.prototype, 'x', {
      value: 0, writable: false, enumerable: true, configurable: false
    });

I see. Then a couple of thoughts:

1. The Declaration production being used here, when used in Statement contexts normally binds names lexically. Here it binds prototype properties. This is not consistent in a sense we might want to make consistent. Allen's http://wiki.ecmascript.org/doku.php?id=strawman:concise_object_literal_extensions strawman provides initialiser extensions for controlling writable, configurable and enumerable.

2. In this light, I do see the value of var instead of const: prior to Harmony, var at top level binds a writable, enumerable, non-configurable global property. True, Harmony gets the global object off the scope chain, but the precedent is there.

Taken together, I wonder whether we aren't abusing Declaration to bind properties.


That said, if we decide we really want a keyword here and can't come up with a better alternative than "var", I probably could be talked into it. And I'm happy to see this added as an option to the strawman.

I'm still not sure we need to bind (enumerable by default, I just noticed -- a for-in hazard) data properties on the class prototype.

I agree that data on the prototype is comparatively rare. But symmetry and consistency sometimes lead us to supporting rare cases, merely to avoid introducing special cases that prohibit them.

Sure, although mixing declaration syntax with property initialiser syntax in class body context invites two conflicting dimensions of consistency. That again makes me wonder whether class body should not consist only of property initialiser variants including methods and constructors.

In particular, given method initialisers, why support function declarations as well?

Also, are nested classes best bound to prototype properties? class A { class B {} ... }; a = new A; b = new a.B; ... is consistent along one dimension but it expresses something super-rare in the prototypal pattern used today, in my view unheard of.

An alternative to property initialisers only, one Dave and I misunderstood the strawman to be proposing: declarations, as opposed to initialisers, bound temporaries once in the lexical scope of the class body, for use by methods and other nested forms. In other words, implicitly private class static bindings. Was this considered?

The simplest idea would be initialisers only, and I know that created a commas-not-semicolons confusion, but that could be changed. Class bodies are neither exactly initialiser nor function bodies, but they might rather be initialiser-like with ; instead of , where a braced body does not terminate the element.


As a ClassElement, "x = y;" is just shorthand for "let x = y;". Likewise "static x = y;" is just shorthand for "static let x = y;".

Except let binds lexically in other declarations. This seems an aesthetic/philosophical objection -- we can make let mean what we like in class body context -- but it also smells bad to me. You?


Also, Gilad Bracha has shown many cool patterns in Newspeak leveraging the ability to inherit a default nested class but being able to override it by a like-named nested class in a subclass. Once you get used to it, it's actually much more natural and expressive than static nested classes.

I think I read Gilad's blog on that a while ago, I'll have to re-read. Again, though, there is nothing like this in idiomatic prototypal JS that I've seen.

/be


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: I noted some open issues on "Classes with Trait Composition"

Brendan Eich-3
In reply to this post by Bob Nystrom
On May 19, 2011, at 5:03 PM, Bob Nystrom wrote:

On Thu, May 19, 2011 at 3:08 PM, Brendan Eich <[hidden email]> wrote:
class Point {
  x = 0;
  ...
}

is a bit of a mystery.

Is it an assignment expression-statement? No, no statements as ClassElements.

Could it be creating a prototype property, as other unprefixed property initialisers such as get and set accessor declarations, and property initialiser extensions declaring prototype methods, do? Yes, that's the intent.

But, I object (mildly), it does not look like a property initialiser. It looks like an assignment expression-statement.

Agreed, completely. My first stab at this used var for declaring fields:

class Point {
  var x = 0; // x field on prototype
}

Yes, I see your point now. Probably we should jump to thread off of my reply to Mark.

/be


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: I noted some open issues on "Classes with Trait Composition"

Brendan Eich-3
In reply to this post by Bob Nystrom
Hi Bob, a few more thoughts/questions/distinctions.

On May 19, 2011, at 1:08 PM, Bob Nystrom wrote:

On Thu, May 19, 2011 at 11:47 AM, Brendan Eich <[hidden email]> wrote:
Here's another question: how many property initializations could be done straight from the parameter of the same name?

Of the 88 fields I looked at, 10 were straight copies of a constructor argument. Another 4 are copies with an "if undefined then use this default instead" check.

??=, check (<a href="http://wiki.ecmascript.org/doku.php?id=strawman:default_operator -- this is going for Harmony gold next week!">http://wiki.ecmascript.org/doku.php?id=strawman:default_operator -- this is going for Harmony gold next week!).


That may be biased a bit low since most of the code I looked at is UI widget-like stuff.

Also, Closure library, right? Opinions vary on the style used there.

Not taking sides, just asking for you lurkers who use other libraries to do similar counting exercises with those libraries, if you all can spare the time. Thanks.


Code that's more data-model oriented would probably have more cases where a class is just wrapping a bunch of arguments.

Apart from the desire to declare per-instance property names, do we really need default values if the constructor author could write default parameter values?

class Point {
  constructor(x = 0, y = 0) {
    this.x = x;
    this.y = y;
  }
 ...
}

That covers a different (though useful!) case. This would be helpful for the 4 cases above where a field is initialized to a constructor argument if given, or to a default value if not.

Hmm, parameter default values != the ??= operator, because while missing actual parameters are undefined, and ??= selects the right-hand side if the left-hand side evaluates to undefined, you can pass undefined followed by other actual parameters to trigger ??=-based defaulting instead of missing (trailing actual) parameter defaulting.

Are the 4 cases all such that the calls to the constructors leave off trailing arguments, or do they pass undefined? Or perhaps they pass other falsy default values, in which case ||= not ??= (and again not parameter default values) could help?

/be


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: I noted some open issues on "Classes with Trait Composition"

Bob Nystrom
In reply to this post by Brendan Eich-3


On Thu, May 19, 2011 at 5:20 PM, Brendan Eich <[hidden email]> wrote:
Taken together, I wonder whether we aren't abusing Declaration to bind properties.

+1. I've been mostly working at this informally and haven't spent much time looking at the EBNF yet, but I'd expect a class body to have its own set of productions just for the small set of members you can define in a class (fields, getters, setters, methods, constants). We may want to expand that a bit (nested classes?), but I like the idea of it being its own set of declaration forms and not just "every declaration ES allows elsewhere".

Also, are nested classes best bound to prototype properties? class A { class B {} ... }; a = new A; b = new a.B; ... is consistent along one dimension but it expresses something super-rare in the prototypal pattern used today, in my view unheard of.

This is a deeply fishy corner case. If you did:

class Outer {
  class Inner {}
}

then the proposal implies Inner would indeed be a property on Outer.prototype, but my strong hunch is users would expect that to be on the ctor (Outer.Inner). To get that, you have to do:

class Outer {
  static class Inner {}
}

An alternative to property initialisers only, one Dave and I misunderstood the strawman to be proposing: declarations, as opposed to initialisers, bound temporaries once in the lexical scope of the class body, for use by methods and other nested forms. In other words, implicitly private class static bindings. Was this considered?

Mark's original proposal treated a class body like a regular lexical scope, which implies having local variables in it. I think the trouble was that it also implied allowing any arbitrary statement inside the class body, and that makes it really hard to have a nice syntax for member declarations (which are what the majority of a class body is). Allowing any statement in there stomps over so much syntactic space that there isn't a lot left for what we care about.

So the consensus we came up with was that a class body isn't a lexical scope and only allows member definitions. That makes it easy to have a nice syntax for those, and gives us breathing room in the future for adding new stuff to classes (like mixins). If you want a lexical scope your class members can access, you can just nest the whole class definition:

let MyClass;
{
  let superSecret = 'shhh!';

  MyClass = class {
    isSecret(maybe) {
      return maybe == superSecret;
    }
  }
}

(There's probably a less awkward way to do that, but you get the idea.)
As a ClassElement, "x = y;" is just shorthand for "let x = y;". Likewise "static x = y;" is just shorthand for "static let x = y;".

Except let binds lexically in other declarations. This seems an aesthetic/philosophical objection -- we can make let mean what we like in class body context -- but it also smells bad to me. You?

Given the choice between let and var for this, I'd lean towards var (or a new keyword entirely), but I could probably be convinced either way.

- bob

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: I noted some open issues on "Classes with Trait Composition"

Bob Nystrom
In reply to this post by Brendan Eich-3


On Thu, May 19, 2011 at 5:40 PM, Brendan Eich <[hidden email]> wrote:
Of the 88 fields I looked at, 10 were straight copies of a constructor argument. Another 4 are copies with an "if undefined then use this default instead" check.

??=, check (http://wiki.ecmascript.org/doku.php?id=strawman:default_operator -- this is going for Harmony gold next week!).

Yup, I like it. :)
 
Also, Closure library, right? Opinions vary on the style used there.

Yeah, code built on top of that, but not part of Closure itself. It would definitely be good to look at other JS too. My professional JS experience is all Closure-style so that likely gives me all sorts of weird biases.
 
Are the 4 cases all such that the calls to the constructors leave off trailing arguments, or do they pass undefined? Or perhaps they pass other falsy default values, in which case ||= not ??= (and again not parameter default values) could help?

For the most part, it's trailing values, but a couple were stuff like:

function SomeClass(opt_a, opt_b) {
  this.a = goog.isDef(opt_a) ? opt_a : SOME_DEFAULT; 
  this.b = goog.isDef(opt_b) ? opt_b : SOME_DEFAULT; 
}

And there may be call sites like new SomeClass(undefined, "blah") I think most people try to minimize those cases, but they seem to crop up, especially as code accretes arguments over time.

- bob

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: I noted some open issues on "Classes with Trait Composition"

Brendan Eich-3
On May 19, 2011, at 6:08 PM, Bob Nystrom wrote:

And there may be call sites like new SomeClass(undefined, "blah") I think most people try to minimize those cases, but they seem to crop up, especially as code accretes arguments over time.

Any use of null instead of undefined for same effect?

/be


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: I noted some open issues on "Classes with Trait Composition"

Juan Ignacio Dopazo
In reply to this post by Brendan Eich-3
On Thu, May 19, 2011 at 9:40 PM, Brendan Eich <[hidden email]> wrote:
Not taking sides, just asking for you lurkers who use other libraries to do similar counting exercises with those libraries, if you all can spare the time. Thanks.

The reality is that in most cases libraries rarely use the constructor(x) { this.x = x } pattern because they tend to create an abstraction to define getters and setters through methods (usually get("prop") and set("prop", value), but sometimes using getProp() and setProp(value)) and use an object as a parameter instead of many parameters. Ie:

var widget = new Widget({
  content: 'hello world',
  title: 'example'
});

This is a very common pattern. Personally I always use it because for me it's always easier to remember parameter names than parameter order. Of course ES5's getters and setters change the situation a lot.


On a side note, there are a couple of aspects in the "object initializer extension" proposal that I liked a lot and which value I think is being underestimated. The class body similar to an object declaration with commas and colons make it very easy to refactor a class into an object and viceversa. This is not only useful for writing, but it also helps reading because it relates complex objects and classes, which is what we're nowadays doing with the most blogged about pattern in JS, the "module pattern", (function(){ return {} }()) and new function () {}.

Is a middle ground possible?

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: I noted some open issues on "Classes with Trait Composition"

Brendan Eich-3
On May 19, 2011, at 6:31 PM, Juan Ignacio Dopazo wrote:

On Thu, May 19, 2011 at 9:40 PM, Brendan Eich <[hidden email]> wrote:
Not taking sides, just asking for you lurkers who use other libraries to do similar counting exercises with those libraries, if you all can spare the time. Thanks.

The reality is that in most cases libraries rarely use the constructor(x) { this.x = x } pattern because they tend to create an abstraction to define getters and setters through methods (usually get("prop") and set("prop", value), but sometimes using getProp() and setProp(value)) and use an object as a parameter instead of many parameters. Ie:

var widget = new Widget({
  content: 'hello world',
  title: 'example'
});

This is a very common pattern. Personally I always use it because for me it's always easier to remember parameter names than parameter order. Of course ES5's getters and setters change the situation a lot.

It's common but I see other styles too, including fixed parameter lists. Good to hear, though -- thanks.


On a side note, there are a couple of aspects in the "object initializer extension" proposal that I liked a lot and which value I think is being underestimated. The class body similar to an object declaration with commas and colons make it very easy to refactor a class into an object and viceversa. This is not only useful for writing, but it also helps reading because it relates complex objects and classes, which is what we're nowadays doing with the most blogged about pattern in JS, the "module pattern", (function(){ return {} }()) and new function () {}.

Is a middle ground possible?

I tend not to think so (tertium non datur), but initialiser syntax really blows for class bodies when you start mixing in declarations. Declarations want to end with ; or } and never comma after }. So holding to initializer syntax only, and being disciplined about it, might work.

/be


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: I noted some open issues on "Classes with Trait Composition"

Brendan Eich-3
On May 19, 2011, at 6:34 PM, Brendan Eich wrote:

On May 19, 2011, at 6:31 PM, Juan Ignacio Dopazo wrote:
On a side note, there are a couple of aspects in the "object initializer extension" proposal that I liked a lot and which value I think is being underestimated. The class body similar to an object declaration with commas and colons make it very easy to refactor a class into an object and viceversa. This is not only useful for writing, but it also helps reading because it relates complex objects and classes, which is what we're nowadays doing with the most blogged about pattern in JS, the "module pattern", (function(){ return {} }()) and new function () {}.

Is a middle ground possible?

I tend not to think so (tertium non datur), but initialiser syntax really blows for class bodies when you start mixing in declarations. Declarations want to end with ; or } and never comma after }. So holding to initializer syntax only, and being disciplined about it, might work.

Of course, get/set and now method property initialisers do end in } and then comma (mandatory if not last property in the outer object initialiser, optional if last). That's a bit confusing if anyone is reading these as declarations (function declarations). In C and C++ you learn and avoid }; at end of function, but since empty top-level declarations are allowed (yay C) this doesn't hurt. In JS you can't leave extra commas after braced bodies in other contexts.

If we succeed in standardizing at least the expression-body part of arrow function syntax (which requires restricting label syntax and refactoring the AssignmentExpression-using non-expression-grammar a bit), then short methods and accessors in initialisers, and perhaps class bodies as you propose, won't have the }, eyesore / syntax trap.

I hope this makes sense,

/be


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: I noted some open issues on "Classes with Trait Composition"

Brendan Eich-3
In reply to this post by Luke Hoban
On May 19, 2011, at 3:00 PM, Luke Hoban wrote:

2) The conventional JS pattern is to place methods on the prototype, not the instance, and many felt that the main thing classes need to provide is a syntax to make this traditional semantics easier to express.

This is the big one.

Class syntax with class parameters instead of explicit constructors can still be defined to produce methods on the prototype, right?

Andreas' example:

 class Point(x, y) {
  public function abs() { return Math.sqrt(x*x, y*y) }
 }

Can effectively desguar to:

 function Point(x,y) {
   this.x = x;
   this.y = y;
 }
 Point.prototype.abs = function() { return Math.sqrt(this.x*this.x, this.y*this.y); }

Try a non-trivial constructor that wants instance properties x and y computed from parameters x0 and y0, and does *not* want properties named x and y.

We should not implicitly create instance properties from class parameter names. I did not take Andreas's message as proposing that.

But let's say the instance variables are declared via

class Point(x0, y0) {
  public x, y;
  ... // somehow set x and y in a constructor body
  public function abs() { return Math.sqrt(x*x, y*y) }
}

Why should there be a non-local rewriting of x and y in function abs to this.x and this.y? Just because they were declared via public?

This is too implicit by far. We need the ability to write constructor bodies that initialize instance properties not necessarily named by constructor parameters. Yes, shorthands for the cliché, e.g.

class Point {
  constructor(this.x, this.y) {}
  ...
}

with parameter default values allowed, are good and (I argue) necessary for competitive reasons. But the full constructor form, whatever it is, must enable parameters to be used freely to compute initial values of instance properties, and some instance properties can have parameter-independent initial values.

And in no case should rewriting or non-lexical scope implicitly come into play to rewrite names in methods to reference instance properties. Shorthands, again, are conceivable and possibly important for usability.

In your example, lexical scoping, the fundamental shared value that enabled Harmony, would have readers think x and y in abs refer to the parameters, *not* to the instance properties. The implicit default constructor copies the parameters to the instance properties, true -- but that's not evident from the syntax.

And since we need the ability to write non-default constructors with explicit property setting on the instance, I do not see how the rewriting of unqualified identifier expressions in method bodies can work -- not without mandating public x, y. But we do not want to mandate declaration of instance properties that the constructor (or any other code) might set.


Or, with private names, to a variant with the captured x and y stored as private fields on the instance.  It's really just a syntax choice between explicit constructor functions and parameterized class definitions.  There are many benefits to the latter, and many modern OO languages seem to be using this style effectively.  

I don't think so. The example needs elaboration to allow for non-default constructor. The non-lexical scope objection applies. And JS is not C# ot any static language. There's a lot to like in many languages but OO does not entail implicit constructors and rewriting.

(I hope you don't mean that the instance (this) should be in the scope chain of each method, because that is non-prototypal and requires a method-clone per instance per prototype (class-declared without keyword prefix) method.)

/be

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: I noted some open issues on "Classes with Trait Composition"

Brendan Eich-3
In reply to this post by Mark S. Miller-2
On May 19, 2011, at 4:01 PM, Mark S. Miller wrote:

> Most other OO languages don't have the this-confusion hazards that JavaScript suffers from.

To put things in a better light, most of those OO languages don't have methods as first class functions, either. (So there! :-P)

/be

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: I noted some open issues on "Classes with Trait Composition"

Andreas Rossberg-4
In reply to this post by Mark S. Miller-2
On 19 May 2011 15:36, Mark S. Miller <[hidden email]> wrote:
> Hi Andreas, yes we have a long history of consider this shape, in fact much
> longer than the current shape. The final state of proposals along these
> lines is
> <http://wiki.ecmascript.org/doku.php?id=strawman:classes_with_trait_composition&rev=1299750065>.

I'll have a closer look, thanks for the pointer!

> 1) Starting from scratch, there's no problem engineering a VM to make
> objects-as-closures efficient, especially given the semi-static analysis
> that class proposal was designed to enable. However, JS VM implementors are
> not starting from scratch. Fitting such a new optimization into existing
> heavily optimized engines was thought to be a hard sell. Especially since
> all major VM implementors would need to agree.
>
> 2) The conventional JS pattern is to place methods on the prototype, not the
> instance, and many felt that the main thing classes need to provide is a
> syntax to make this traditional semantics easier to express.
> Another variation of your suggestion that Tom suggested is that you mix
> instance initialization and class/prototype initialization together in the
> class body. This obscures both time-of-execution and scope. Methods on the
> prototype do cannot have the constructor parameters in scope.

Like Luke I was wondering why a change of syntax should affect the
semantics. But after seeing your reply pointing out the problem with
`this', I see your point. Although it doesn't seem to specific to
constructor parameters, but would apply to instance fields in general
with the class-as-block approach. Still sad.

I agree that the ideal solution would be objects-as-closures.
Personally, though, I could also live with requiring instance
variables and constructor arguments always be accessed through `this',
even in that syntactic approach. True, it somewhat obscures scoping --
but arguably, "public" or "private" declarations are not ordinary
declarations, so it's not too hard to argue that they do not actually
bind anything in the "current" scope. Same goes for constructor
arguments vs ordinary function arguments.

Thanks,
/Andreas
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: I noted some open issues on "Classes with Trait Composition"

Andreas Rossberg-4
In reply to this post by Dave Herman
On 19 May 2011 16:05, David Herman <[hidden email]> wrote:
> Yes, we've talked about this. One of the issues I don't know how to resolve is if we want to allow the specification of class properties aka statics, then those need *not* to be in the scope of the constructor arguments, which ends up with very strange scoping behavior:
>
>    var x = "outer"
>    class C(x) {
>        static foo = x // "outer" -- whoa!
>    }
>
> I'm not 100% up on the current thinking of the group that's been working on classes, and whether they are including statics in the design, but I think they are.

Oh, it wasn't clear to me that we really want to have static members.
I may be biased here, but I always viewed static members as just a
poor man's substitute for a proper module system. Fortunately, it
looks like we will have a real one instead!

To be honest, I'm a bit worried that there will be a _lot_ of semantic
redundancy in the end. After adding modules + classes + static members
(+ traits?), there would be at least three or four different,
complicated constructs that evaluate to some kind of object, with
significant functional overlap.

Thanks,
/Andreas
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: I noted some open issues on "Classes with Trait Composition"

Mark S. Miller-2

Modules aren't generative.

sent from android

On May 20, 2011 7:58 AM, "Andreas Rossberg" <[hidden email]> wrote:
> On 19 May 2011 16:05, David Herman <[hidden email]> wrote:
>> Yes, we've talked about this. One of the issues I don't know how to resolve is if we want to allow the specification of class properties aka statics, then those need *not* to be in the scope of the constructor arguments, which ends up with very strange scoping behavior:
>>
>>    var x = "outer"
>>    class C(x) {
>>        static foo = x // "outer" -- whoa!
>>    }
>>
>> I'm not 100% up on the current thinking of the group that's been working on classes, and whether they are including statics in the design, but I think they are.
>
> Oh, it wasn't clear to me that we really want to have static members.
> I may be biased here, but I always viewed static members as just a
> poor man's substitute for a proper module system. Fortunately, it
> looks like we will have a real one instead!
>
> To be honest, I'm a bit worried that there will be a _lot_ of semantic
> redundancy in the end. After adding modules + classes + static members
> (+ traits?), there would be at least three or four different,
> complicated constructs that evaluate to some kind of object, with
> significant functional overlap.
>
> Thanks,
> /Andreas

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: I noted some open issues on "Classes with Trait Composition"

Dave Herman
In reply to this post by Andreas Rossberg-4
> Oh, it wasn't clear to me that we really want to have static members.
> I may be biased here, but I always viewed static members as just a
> poor man's substitute for a proper module system. Fortunately, it
> looks like we will have a real one instead!

I'm sympathetic to that view, but statics also have precedent in JS, so I would bet people will continue to use them. I think it's not unreasonable to want a declarative way to create members of the constructor function object. That said, in the interest of parsimony, if we had to start cutting, statics would probably be one of the first I'd eliminate.

> To be honest, I'm a bit worried that there will be a _lot_ of semantic
> redundancy in the end. After adding modules + classes + static members
> (+ traits?), there would be at least three or four different,
> complicated constructs that evaluate to some kind of object, with
> significant functional overlap.

I think "modules are a construct that evaluates to an object" is the wrong way to think about them. Syntactic modules are a second-class construct that is not an expression. You can reflect on modules at runtime, and that reflection is provided as an object, but that's because almost all compound data structures in JS are objects. But I would advise against describing modules as a kind of object.

And I think an important aspect of classes is that they are providing a declarative convenience for doing things that people *already* do with objects in JS today.

So I'm not as worried about redundancy here.

Dave

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: I noted some open issues on "Classes with Trait Composition"

Bob Nystrom
In reply to this post by Brendan Eich-3
On Thu, May 19, 2011 at 6:13 PM, Brendan Eich <[hidden email]> wrote:
On May 19, 2011, at 6:08 PM, Bob Nystrom wrote:

And there may be call sites like new SomeClass(undefined, "blah") I think most people try to minimize those cases, but they seem to crop up, especially as code accretes arguments over time.

Any use of null instead of undefined for same effect?

If I recall, there are places where we do that but I think most of the code I've seen tries to use undefined

- bob


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Modules first or second class (Re: I noted some open issues on "Classes with Trait Composition")

Claus Reinke
In reply to this post by Dave Herman
> I think "modules are a construct that evaluates to an
> object" is the wrong way to think about them. Syntactic
> modules are a second-class construct that is not an
> expression. You can reflect on modules at runtime,
> and that reflection is provided as an object, but that's
> because almost all compound data structures in JS
> are objects. But I would advise against describing
> modules as a kind of object.

Just a note on this: for me, that means Harmony modules
are a step back from what I can implement in JS/now. Not
having first-class modules has been a major drawback in
Haskell (which has a strictly 1980s-style module system),
leading to all kinds of work-arounds.

One of these workarounds, which I expect to see and use
a lot in Harmony, is to have first-class modules-as-records
(or objects) inside second-class built-in-modules.

Is this an intended outcome of the Harmony module design?

For instance, I've got a parser-combinator library and
a (near) ES5 grammar built on it, and to test, I pass one
module to the other, and both modules to the tester:

    test(source, options, pc, grammar(pc))

Strictly speaking, the pc module also depends on the
grammar module, for grammar-specified whitespace,
but cyclic structures are a bit awkward in Javascript.

Claus
 
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Modules first or second class (Re: I noted some open issues on "Classes with Trait Composition")

Brendan Eich-3
On May 20, 2011, at 2:51 PM, Claus Reinke wrote:

>> I think "modules are a construct that evaluates to an object" is the wrong way to think about them. Syntactic modules are a second-class construct that is not an expression. You can reflect on modules at runtime, and that reflection is provided as an object, but that's because almost all compound data structures in JS are objects. But I would advise against describing modules as a kind of object.
>
> Just a note on this: for me, that means Harmony modules
> are a step back from what I can implement in JS/now.

That's false, since you cannot implement what second class modules provide in JS now without a preprocessor. You cannot, by special forms such as the module M = ... form, tell the compiler to prefetch or find memoized a certain module.


> Not
> having first-class modules has been a major drawback in
> Haskell (which has a strictly 1980s-style module system),
> leading to all kinds of work-arounds.

Yes, the CMU folks were buggin'. But: please try to look at JS as it is, not just reference Haskell.


> One of these workarounds, which I expect to see and use
> a lot in Harmony, is to have first-class modules-as-records
> (or objects) inside second-class built-in-modules.

Why?

If you want first-class objects, use objects (frozen if you like). If you want functions, they're in JS already.

Generative classes by nesting in a maker function fall out cleanly from this design.


> Is this an intended outcome of the Harmony module design?

Please read the proposal page.

http://wiki.ecmascript.org/doku.php?id=harmony:modules

It's all there: static scoping, orthogonality, etc.

/be
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Modules first or second class (Re: I noted some open issues on "Classes with Trait Composition")

Kam Kasravi
In reply to this post by Claus Reinke
This is sort of an interesting point. In a related question I've wondered about how narcissus could use modules in lieu of
its current way of eval'ing definitions.const in jslex and jsparse in order to get the operators, tokens and keywords in local scope
for both the lexer and the parser. If narcissus were to take advantage of harmony could jsparse, jslex do an 'import jsdefs.consts' as an alternative?


From: Claus Reinke <[hidden email]>
To: David Herman <[hidden email]>
Cc: [hidden email]
Sent: Friday, May 20, 2011 2:51 PM
Subject: Modules first or second class (Re: I noted some open issues on "Classes with Trait Composition")

> I think "modules are a construct that evaluates to an object" is the wrong way to think about them. Syntactic modules are a second-class construct that is not an expression. You can reflect on modules at runtime, and that reflection is provided as an object, but that's because almost all compound data structures in JS are objects. But I would advise against describing modules as a kind of object.

Just a note on this: for me, that means Harmony modules
are a step back from what I can implement in JS/now. Not
having first-class modules has been a major drawback in
Haskell (which has a strictly 1980s-style module system),
leading to all kinds of work-arounds.
One of these workarounds, which I expect to see and use
a lot in Harmony, is to have first-class modules-as-records
(or objects) inside second-class built-in-modules.

Is this an intended outcome of the Harmony module design?

For instance, I've got a parser-combinator library and
a (near) ES5 grammar built on it, and to test, I pass one
module to the other, and both modules to the tester:

  test(source, options, pc, grammar(pc))

Strictly speaking, the pc module also depends on the grammar module, for grammar-specified whitespace,
but cyclic structures are a bit awkward in Javascript.

Claus

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



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Modules first or second class (Re: I noted some open issues on "Classes with Trait Composition")

Dave Herman
Yep! By making modules static, we introduce much cleaner ways of sharing constants. Responding to Claus in a sec...

Dave

On May 20, 2011, at 3:21 PM, Kam Kasravi wrote:

This is sort of an interesting point. In a related question I've wondered about how narcissus could use modules in lieu of
its current way of eval'ing definitions.const in jslex and jsparse in order to get the operators, tokens and keywords in local scope
for both the lexer and the parser. If narcissus were to take advantage of harmony could jsparse, jslex do an 'import jsdefs.consts' as an alternative?


From: Claus Reinke <[hidden email]>
To: David Herman <[hidden email]>
Cc: [hidden email]
Sent: Friday, May 20, 2011 2:51 PM
Subject: Modules first or second class (Re: I noted some open issues on "Classes with Trait Composition")

> I think "modules are a construct that evaluates to an object" is the wrong way to think about them. Syntactic modules are a second-class construct that is not an expression. You can reflect on modules at runtime, and that reflection is provided as an object, but that's because almost all compound data structures in JS are objects. But I would advise against describing modules as a kind of object.

Just a note on this: for me, that means Harmony modules
are a step back from what I can implement in JS/now. Not
having first-class modules has been a major drawback in
Haskell (which has a strictly 1980s-style module system),
leading to all kinds of work-arounds.
One of these workarounds, which I expect to see and use
a lot in Harmony, is to have first-class modules-as-records
(or objects) inside second-class built-in-modules.

Is this an intended outcome of the Harmony module design?

For instance, I've got a parser-combinator library and
a (near) ES5 grammar built on it, and to test, I pass one
module to the other, and both modules to the tester:

  test(source, options, pc, grammar(pc))

Strictly speaking, the pc module also depends on the grammar module, for grammar-specified whitespace,
but cyclic structures are a bit awkward in Javascript.

Claus

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




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