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

Mark S. Miller erights at google.com
Mon May 23 10:42:44 PDT 2011


On Mon, May 23, 2011 at 2:16 PM, Andreas Rossberg <rossberg at google.com>wrote:

> On 20 May 2011 18:00, David Herman <dherman at mozilla.com> 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.
> >
> > 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.
>
> I see what you are saying, and yes, they are intended to serve a
> different purpose. But they still share a lot of semantic overlap. And
> I foresee that the overlap will increase overtime, as the language
> evolves.
>
> Take just one specific example: there already is the proposal for
> extending modules with "module functions"
> (http://wiki.ecmascript.org/doku.php?id=strawman:simple_module_functions)
> -- which makes a lot of sense, is straightforward, and I'm sure that
> people will demand something along these lines sooner or later. But
> for better or worse, modules now actually have become classes!
> Compare:
>
>  class Point {
>    private x, y
>    constructor(x0, y0) { x = x0; y = y0 }
>    public function move(dx, dy) { x += dx; y += dy }
>     public function abs() { return Math.sqrt(x*x, y*y) }
>  }
>
>   let p = new Point(3, 4)
>  p.abs()
>
> with:
>
>  module Point(x0, y0) {
>    let x = x0, y = y0
>    export function move(dx, dy) { x += dx; y += dy }
>    export function abs() { return Math.sqrt(x*x, y*y) }
>  }
>
>  let p = Point(3, 4)  // assuming module functions are reflected into
> functions
>  p.abs()
>
> Almost the same effect, even though the underlying semantics differs
> somewhat.


Regarding the scoping of private instance variables, the version with
generative module functions is actually much better[1]. In fact, it's the
same as the objects-as-closures pattern, or the earlier <
http://wiki.ecmascript.org/doku.php?id=strawman:classes_with_trait_composition&rev=1299750065>
classes strawman, which is essentially a codification of
objects-as-closures. Personally, I still like that earlier strawman better.
But I gave up on it based on the difficulty of convincing implementors to
implement it efficiently. Your's seems to have the same efficiency issue.
Since you are now involved in JS implementation, let me ask regarding your
efforts:

In the above example, do you anticipate an allocation per method per
instance? Specifically, does each call to Point allocate a new instance of
the point module (fine) exporting newly allocated move and abs closures
(bad). Some codification of objects-as-closures only becomes a viable
alternative to the current manual class pattern if it can avoid these extra
allocations.

Putting methods on a shared prototype essentially treats the prototype as a
vtable. This implementation path is messy, but is well trodden in current JS
implementations. Avoiding extra allocations for objects-as-closures, whether
sugared by your generative module pattern on my earlier classes strawman,
would seem to require a new vtable mechanism not directly mapped onto
prototype inheritance. Perhaps the "hidden classes" optimization already
provides a context in which we can reuse implementation machinery between
these two vtable-like mechanisms?

[1] The semantics of the "x" reference in your move and abs methods differs
so violently from a lexical variable reference <
https://mail.mozilla.org/pipermail/es-discuss/2011-May/014516.html> that we
must not make it appear to be a lexical variable reference. Starting with
ES5, we have finally rescued lexical scoping from JavaScript's messy past.
Let's not lose the ground we gained. Brevity is important, but scoping
clarity is way more important than brevity.



> You can even express simple inheritance with import and
> export, depending on how general they will be in the end.
>
> Obviously, there are aspects that you still cannot express with
> modules but can with classes, and vice versa. But my point is that at
> their core, they end up being pretty similar things. And their
> differences might eventually start looking rather accidental. I would
> feel better if we thought a bit harder about ways to utilize the
> commonalities before we grow the size of the language too quickly.
>

Today is the day before the May meeting. If generative module functions
could be grown to meet the needs of classes, I think I would prefer the
outcome as compared to the current classes strawman. However, the open
issues that would need to be explored to determine this vastly exceeds the
time between now and then.

The May meeting is the close of the "additive phase" of designing ES-next.
Following that, we hope for some consolidation and subtraction, among other
activities (prototype implementations, web testing, spec writing,
etc). Modules are already in. If classes get accepted in May, then I would
consider it in bounds after May to grow modules slightly in order to remove
classes completely. This would seem to be an excellent tradeoff. As I
recall, you were planning to be at the July meeting? I think this would be a
good focus topic for July.


>
> /Andreas
>



-- 
    Cheers,
    --MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110523/d0c7f18c/attachment.html>


More information about the es-discuss mailing list