Re: Proposal: Improve syntax for inline anonymous class instantiations

2017-01-08 Thread Igor Vaynberg

> On Jan 7, 2017, at 4:45 AM, Alexander Jones  wrote:
> 
> Hi Igor
> 
> With `super()` and closure binding of the anonymous class `constructor` (as 
> with all class methods) you can basically solve your problem of constructor 
> arguments appearing in the wrong place:
> 
> ```
> this.add(
> new class extends ArrayView {
> constructor() { super("items", itemsModel); }
> populateItem(item) {
> item.add(new Checkbox("check", new PropertyModel(item.model, 
> "done")));
> item.add(new Label("title", new PropertyModel(item.model, 
> "title")));
> }
> }
> );
> ```
> 
> I concede that spelling `constructor`, `super`, and the various soup of 
> punctuation is a little less than ideal, but at the end of the day I think 
> this is quite reasonable, don't you?

Yes, indeed. Thanks Alexander. I don't know why I didnt think of that myself. 
It is a little soupy since it adds an extra line and four extra keywords, but 
at least it allows this style of code.

Thanks again,
-Igor

> 
> Cheers
> 
> Alex
> 
> On 6 January 2017 at 22:11, Igor Vaynberg  > wrote:
> Given a simple class with an abstract method "populateItem"
> 
> class ArrayView extends Container {
> constructor(id, model) {
> super(id);
> this.model = model;
> }
> 
> // methods referencing "populateItem" omitted for clarity
> }
> 
> the current anonymous instantiation syntax looks like this:
> 
> this.add(new class extends ArrayView {
> populateItem(item) {
> item.add(new Checkbox("check", new PropertyModel(item.model, 
> "done")));
> item.add(new Label("title", new PropertyModel(item.model, "title")));
> }
> }
> ("items", itemsModel)
> );
> 
> The problem with this syntax is that it pushes the constructor
> parameters below the class body which I think causes two problems:
> 
> When scanning code constructors often contain the piece of information
> that helps locate the anonymous class, which currently requires the
> developer to look back. This is especially problematic for anonymous
> classes with long class bodies.
> 
> When writing code I usually think about the constructor first, so it
> seems it would be preferable to write it before moving onto working on
> the class body. This is also the reason why constructors are usually
> placed toward the top of named classes' source.
> 
> A better syntax would move the constructor parameters between the
> super class name and the class body:
> 
> this.add(new class extends ArrayView("items", itemsModel) {
> populateItem(item) {
> item.add(new Checkbox("check", new PropertyModel(item.model, 
> "done")));
> item.add(new Label("title", new PropertyModel(item.model, "title")));
> }
> });
> 
> If possible it would also be great to get rid of the "class extends"
> keywords for this usecase:
> 
> this.add(new ArrayView("items", itemsModel) {
> populateItem(item) {
> item.add(new Checkbox("check", new PropertyModel(item.model, 
> "done")));
> item.add(new Label("title", new PropertyModel(item.model, "title")));
> }
> });
> 
> Thoughts?
> 
> 
> Thanks,
> -igor
> ___
> es-discuss mailing list
> es-discuss@mozilla.org 
> https://mail.mozilla.org/listinfo/es-discuss 
> 
> 

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: Improve syntax for inline anonymous class instantiations

2017-01-07 Thread Alexander Jones
Hi Igor

With `super()` and closure binding of the anonymous class `constructor` (as
with all class methods) you can basically solve your problem of constructor
arguments appearing in the wrong place:

```
this.add(
new class extends ArrayView {
constructor() { super("items", itemsModel); }
populateItem(item) {
item.add(new Checkbox("check", new PropertyModel(item.model,
"done")));
item.add(new Label("title", new PropertyModel(item.model,
"title")));
}
}
);
```

I concede that spelling `constructor`, `super`, and the various soup of
punctuation is a little less than ideal, but at the end of the day I think
this is quite reasonable, don't you?

Cheers

Alex

On 6 January 2017 at 22:11, Igor Vaynberg  wrote:

> Given a simple class with an abstract method "populateItem"
>
> class ArrayView extends Container {
> constructor(id, model) {
> super(id);
> this.model = model;
> }
>
> // methods referencing "populateItem" omitted for clarity
> }
>
> the current anonymous instantiation syntax looks like this:
>
> this.add(new class extends ArrayView {
> populateItem(item) {
> item.add(new Checkbox("check", new PropertyModel(item.model,
> "done")));
> item.add(new Label("title", new PropertyModel(item.model,
> "title")));
> }
> }
> ("items", itemsModel)
> );
>
> The problem with this syntax is that it pushes the constructor
> parameters below the class body which I think causes two problems:
>
> When scanning code constructors often contain the piece of information
> that helps locate the anonymous class, which currently requires the
> developer to look back. This is especially problematic for anonymous
> classes with long class bodies.
>
> When writing code I usually think about the constructor first, so it
> seems it would be preferable to write it before moving onto working on
> the class body. This is also the reason why constructors are usually
> placed toward the top of named classes' source.
>
> A better syntax would move the constructor parameters between the
> super class name and the class body:
>
> this.add(new class extends ArrayView("items", itemsModel) {
> populateItem(item) {
> item.add(new Checkbox("check", new PropertyModel(item.model,
> "done")));
> item.add(new Label("title", new PropertyModel(item.model,
> "title")));
> }
> });
>
> If possible it would also be great to get rid of the "class extends"
> keywords for this usecase:
>
> this.add(new ArrayView("items", itemsModel) {
> populateItem(item) {
> item.add(new Checkbox("check", new PropertyModel(item.model,
> "done")));
> item.add(new Label("title", new PropertyModel(item.model,
> "title")));
> }
> });
>
> Thoughts?
>
>
> Thanks,
> -igor
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: Improve syntax for inline anonymous class instantiations

2017-01-07 Thread T.J. Crowder
Two aspects to this: Motivations and syntax.

## On motivations:

Addressing new syntax, the first question has to be: Is this use case
sufficiently common and painful that it needs new syntax? The answer
may be yes, but we need to ask the question.

Trying to solve it without new syntax with a helper function, I've
come up with three ways of getting those arguments up front. I'm not
all that happy with any of them.

### Helper #1:

This kind of has the opposite problem (the class is hidden away at the
end), but it's dead simple:

```js
this.add(makeInstance("items", itemsModel, class extends ArrayView {
populateItem(item) {
item.add(new Checkbox("check", new PropertyModel(item.model, "done")));
item.add(new Label("title", new PropertyModel(item.model, "title")));
}
}));
```

...where `makeInstance` is:


```js
const makeInstance = (...args) => {
return new args[args.length - 1](...args.slice(0, args.length - 1));
};
```

### Helper #2:

Puts things in the desired order, but isn't exactly elegant at point-of-use:

```js
this.add(makeInstance(ArrayView, "items", itemsModel, parent => class
extends parent {
populateItem(item) {
item.add(new Checkbox("check", new PropertyModel(item.model, "done")));
item.add(new Label("title", new PropertyModel(item.model, "title")));
}
}));
```

...where `makeInstance` is:


```js
const makeInstance = (parent, ...rest) => {
const args = rest.slice(0, rest.length - 1);
const subclass = rest[rest.length - 1](parent);
return new subclass(...args);
};
```

### Helper #3:

Gets really close in terms of usage, but because the methods would
have the wrong [[HomeObject]] (Igor's example didn't use `super` in
`populateItem` but presumably it could have), it has to resort to not
one but two `setPrototypeOf` calls, which is just ugly:

```js
this.add(makeInstance(ArrayView, "items", itemsModel, {
populateItem(item) {
item.add(new Checkbox("check", new PropertyModel(item.model, "done")));
item.add(new Label("title", new PropertyModel(item.model, "title")));
}
}));
```

...where `makeInstance` is:

```js
const makeInstance = (cls, ...rest) => {
const args = rest.slice(0, rest.length - 1);
const methods = rest[rest.length - 1];
const subclass = class extends cls { };
Object.setPrototypeOf(methods, cls.prototype);
Object.setPrototypeOf(subclass.prototype, methods);
return new subclass(...args);
};
```

(Hey, I warned you it was ugly.) (This isn't the first time I've
wanted to change a method's [[HomeObject]] after creation.)

Maybe someone else can do better.

Or, of course, just don't use an anonymous class.

## On syntax:

Looking at:

```js
this.add(new ArrayView("items", itemsModel) {
populateItem(item) {
item.add(new Checkbox("check", new PropertyModel(item.model, "done")));
item.add(new Label("title", new PropertyModel(item.model, "title")));
}
});
```

A couple of notes/observations:

* This is exactly how Java handles [doing the same
thing](http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html).
JavaScript is not Java, of course, but worth noting prior art.

* It would be good to hear early from implementers if this presents a
parsing challenge. Until the `{`, it looks like you're instantiating
`ArrayView` with `"items"` and `itemsModel`; the `{` then changes
things. I don't know if that's backtracking, or looking ahead, or
what. Obviously Java parsers handle it, but again, different language,
different challenges.

* If you remove the `this.add(...)` part of that, there's an ASI
hazard if you put a line break before the `{` -- it becomes `new
ArrayView("items", itemsModel);` followed by a block (which then has
invalid content). (Not an insurmountable problem, it's not like it's
the only ASI hazard caused by a line break before a `{`. But it would
add another one.)

-- T.J.
Farsight Software Ltd | 20-22 Wenlock Road, London N1 7GU | Company #8393428

tj.crow...@farsightsoftware.com | Direct: +44 (0)20 3627 4231 |
Mobile: +44 (0)7717 842 414



If you've received this message in error, please let us know by
forwarding it to i...@farsightsoftware.com and then delete it from
your system. Please don't copy it or disclose its contents to anyone.
Separately, note that email sent over the internet without a digital
signature may be modified en route.


On Sat, Jan 7, 2017 at 5:35 AM, Igor Vaynberg  wrote:
>
>> On Jan 6, 2017, at 7:04 PM, Allen Wirfs-Brock  wrote:
>>
>> (new class extends foo(bar) {…})
>> is already valid syntax that means use the value return from calling foo 
>> with argument bar as the superclass of the class that is being instantiated. 
>> What you propose would be a breaking change.
>
> What about limiting it just to (new foo(bar) {...}) syntax?
>
> -igor
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> 

Re: Proposal: Improve syntax for inline anonymous class instantiations

2017-01-06 Thread Igor Vaynberg

> On Jan 6, 2017, at 7:04 PM, Allen Wirfs-Brock  wrote:
> 
> (new class extends foo(bar) {…})
> is already valid syntax that means use the value return from calling foo with 
> argument bar as the superclass of the class that is being instantiated. What 
> you propose would be a breaking change.

What about limiting it just to (new foo(bar) {...}) syntax?

-igor

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: Improve syntax for inline anonymous class instantiations

2017-01-06 Thread Allen Wirfs-Brock
(new class extends foo(bar) {…})
is already valid syntax that means use the value return from calling foo with 
argument bar as the superclass of the class that is being instantiated. What 
you propose would be a breaking change.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: Improve syntax for inline anonymous class instantiations

2017-01-06 Thread Matthew Robb
For some reason this idea made me think about adding extends to function
syntax:
```
class Foo {}

function Bar(a, b) extends Foo {
  // ...
}

// Basic sugar for

function Baz(a, b) {
  // ...
}

Object.setPrototypeOf(Baz, Foo);
Object.setPrototypeOf(Baz.prototype, Foo.prototype);

```

Although now that I re-read the original post I don't think this addresses
the same scenario


- Matthew Robb

On Fri, Jan 6, 2017 at 5:11 PM, Igor Vaynberg 
wrote:

> Given a simple class with an abstract method "populateItem"
>
> class ArrayView extends Container {
> constructor(id, model) {
> super(id);
> this.model = model;
> }
>
> // methods referencing "populateItem" omitted for clarity
> }
>
> the current anonymous instantiation syntax looks like this:
>
> this.add(new class extends ArrayView {
> populateItem(item) {
> item.add(new Checkbox("check", new PropertyModel(item.model,
> "done")));
> item.add(new Label("title", new PropertyModel(item.model,
> "title")));
> }
> }
> ("items", itemsModel)
> );
>
> The problem with this syntax is that it pushes the constructor
> parameters below the class body which I think causes two problems:
>
> When scanning code constructors often contain the piece of information
> that helps locate the anonymous class, which currently requires the
> developer to look back. This is especially problematic for anonymous
> classes with long class bodies.
>
> When writing code I usually think about the constructor first, so it
> seems it would be preferable to write it before moving onto working on
> the class body. This is also the reason why constructors are usually
> placed toward the top of named classes' source.
>
> A better syntax would move the constructor parameters between the
> super class name and the class body:
>
> this.add(new class extends ArrayView("items", itemsModel) {
> populateItem(item) {
> item.add(new Checkbox("check", new PropertyModel(item.model,
> "done")));
> item.add(new Label("title", new PropertyModel(item.model,
> "title")));
> }
> });
>
> If possible it would also be great to get rid of the "class extends"
> keywords for this usecase:
>
> this.add(new ArrayView("items", itemsModel) {
> populateItem(item) {
> item.add(new Checkbox("check", new PropertyModel(item.model,
> "done")));
> item.add(new Label("title", new PropertyModel(item.model,
> "title")));
> }
> });
>
> Thoughts?
>
>
> Thanks,
> -igor
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss