Re: Can `new` be optional?

2017-11-05 Thread Andrea Giammarchi
> Why does calling a class throw an exception instead of just creating a
new instance

backward compatibility and early "rushed" behavior is one of the reasons.

`String() instanceof String` is false and it's just one example.

Because of primitives and `typeof`, `new Symbol` throws too, you are not
meant to do that.

Array and Regexp though, have no primitive namespace, but that's old gotcha
later specs tried to prevent.

What about `new Date` ? Now that's an instance, while `Date()` is a string.

Using `new` makes your intent unambiguous in a PL where functions can be
used as constructors too.

There is also the possibility to create functions that cannot be used as
`new`:

```js
const method = {method(){}}.method;

new method; // throws
```

Accordingly, since you have Reflect for all procedural use cases, what is
the benefit of not using `new` where it's an instance of that Class you are
after?
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Can `new` be optional?

2017-11-05 Thread Logan Smyth
> I also don't see how decorators can solve it.

Making to wrapper for class constructor to allow the constructor to
callable would be fairly straightforward, e.g.

```
function callable(cls) {
  function Wrapper(...args) {
return Reflect.construct(cls, args, new.target || cls);
  }
  Object.defineProperty(Wrapper, "name", { value: cls.name });
  Object.setPrototypeOf(Wrapper, cls);
  Wrapper.prototype = cls.prototype;
  return Wrapper;
}

const Example = callable(class Example {});

Example();
```
and thus potentially
```
@callable
class Example {}
```

I know you said "At the cost of non-zero overhead." but it seems like this
would be something engines could optimize more easily than proxies.

> This seems like a really short sighted issue.  Why can't calling a class
just invoke it's constructor?

I think the big question for me when discussing this with people is, is it
more surprising to throw a clear error in these case, or to do something
close but not quite the same as if it were an ES5-style constructor?

```
class Foo {
  constructor() {
this.foo = 4;
  }
}

var obj = {};
var inst = Foo.call(obj);

// what happens?
// obj.foo => 4 or undefined
// inst => obj, new object, or undefined
// inst.foo => 4 or undefined
```
To be consistent with ES6 class semantics it has to be that a new instance
is returned and `obj` is 100% ignored but that are very much not what you'd
get if you replaced the class there with `function Foo(){ this.foo = 4; }`.
Isn't that its own set of confusing changes?

Specifically for "This seems like a really short sighted issue" I'd say
this is the opposite of short-sighted. There's nothing preventing support
for this in the future, but if it got added with a behavior that ended up
confusing people _more_ than not having it at all, then we'd be stuck with
it for good.


On Sun, Nov 5, 2017 at 11:53 AM, J Decker  wrote:

>
>
> On Sun, Nov 5, 2017 at 7:53 AM, Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> oldie but goldie ?
>>
>> ```js
>> Object.defineProperty(
>>   Function.prototype,
>>   'new',
>>   {
>> configurable: true,
>> value(...args) {
>>   return new this(...args);
>> }
>>   }
>> );
>> ```
>>
>> doesn't make new optional, just moves it, and doesn't apply to 'class'es
> which the OP is saying.
>
>
>>
>>
>>
>>
>> On Sun, Nov 5, 2017 at 11:28 AM, Oriol _ 
>> wrote:
>>
>>> > Why can't `new` be optional?
>>>
>>> When you call a function, you are using the internal [[Call]] method.
>>> When you use the `new` operator, it's the internal [[Construct]] method.
>>>
>>> They are different things, so IMO avoiding `new` when you are
>>> instantiating is bad practice.
>>>
>>>
> Of course it is... with out new, classes throw an exception.
>
> This seems like a really short sighted issue.  Why can't calling a class
> just invoke it's constructor?
>
> I also don't see how decorators can solve it.
>
> Seems just as arbitrary as the underscore proposal not accepting
> underscore trailing a number or before or after a decimal.
>
> Maybe, it would be better to ask 'Why does calling a class throw an
> exception instead of just creating a new instance.
>
>
>> But if you really want to avoid `new` when using ES6 `class` syntax, you
>>> can use proxies, e.g.
>>>
>>> ```js
>>> let MyClass = new Proxy(class MyClass {
>>>   constructor(arg) { this.arg = arg; }
>>> }, {
>>>   apply: (target, thisArg, args) => Reflect.construct(target, args)
>>> });
>>> MyClass(1); // { arg: 1 }
>>> new MyClass(2); // { arg: 2 }
>>> ```
>>>
>>
> At the cost of non-zero overhead.
>
>
>> --Oriol
>>>
>>> ___
>>> 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
>>
>>
>
> ___
> 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: Syntax is the Problem

2017-11-05 Thread Alexander Jones
This is projective editing. See for example https://www.jetbrains.com/mps/

On 5 November 2017 at 13:22, Michael Lewis  wrote:

> Raul-Sebastian Mihăilă just made a post here about some mixin syntax.  I
> didn't read it (sorry).
>
> But, it got me thinking about a concept I've been thinking for years:  *syntax
> is the problem*, and there's a better solution.
>
> If you define syntax as a human <--> computer language (a human-readable
> and computer-readable form of text), you necessarily need a very strictly
> defined syntax.  One missing curly, and you're f'd.
>
> Duh, we all know this.  Hang onto your pants for a second, let's explore
> an alternative.
>
> What if we edited scripts more directly in AST form (abstract syntax
> tree).  Developers could implement their own UI to manipulate this AST.
> There are many, many benefits to this, I'll get to in a second.
>
> First, let's remember what everyone in the JS community is doing right
> now:  running their code through transpilers.  (I refuse to do this, that's
> why I'm unemployed - I strongly dislike the concept).  What is a
> transpiler?  It's an unofficial middleman that interprets the syntax,
> converts it to an AST, performs transformations, and then returns the AST
> to syntax form.
>
> Suddenly, scripting in AST form doesn't sound so crazy.
>
> Clearly, you wouldn't be writing JSON.  We would be using a GUI to create
> the AST.  And this is the greatest benefit: moving away from *syntax*,
> and moving to a GUI.
>
> Then, instead of babel plugins that provide alternative *syntax*, you
> could have plugins that provide alternative *experiences.*
>
> What would designing a class look like, if using a GUI?
>
>1. Click [ create new class ]
>2. Click [ add new method ]
>
> Or, click the [ extend ] button next to an existing class...
>
> This is the future.  I have to go eat breakfast, but I'd love to discuss
> this future if anyone is interested...
>
> ___
> 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: Can `new` be optional?

2017-11-05 Thread J Decker
On Sun, Nov 5, 2017 at 7:53 AM, Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> oldie but goldie ?
>
> ```js
> Object.defineProperty(
>   Function.prototype,
>   'new',
>   {
> configurable: true,
> value(...args) {
>   return new this(...args);
> }
>   }
> );
> ```
>
> doesn't make new optional, just moves it, and doesn't apply to 'class'es
which the OP is saying.


>
>
>
>
> On Sun, Nov 5, 2017 at 11:28 AM, Oriol _ 
> wrote:
>
>> > Why can't `new` be optional?
>>
>> When you call a function, you are using the internal [[Call]] method.
>> When you use the `new` operator, it's the internal [[Construct]] method.
>>
>> They are different things, so IMO avoiding `new` when you are
>> instantiating is bad practice.
>>
>>
Of course it is... with out new, classes throw an exception.

This seems like a really short sighted issue.  Why can't calling a class
just invoke it's constructor?

I also don't see how decorators can solve it.

Seems just as arbitrary as the underscore proposal not accepting underscore
trailing a number or before or after a decimal.

Maybe, it would be better to ask 'Why does calling a class throw an
exception instead of just creating a new instance.


> But if you really want to avoid `new` when using ES6 `class` syntax, you
>> can use proxies, e.g.
>>
>> ```js
>> let MyClass = new Proxy(class MyClass {
>>   constructor(arg) { this.arg = arg; }
>> }, {
>>   apply: (target, thisArg, args) => Reflect.construct(target, args)
>> });
>> MyClass(1); // { arg: 1 }
>> new MyClass(2); // { arg: 2 }
>> ```
>>
>
At the cost of non-zero overhead.


> --Oriol
>>
>> ___
>> 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
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Syntax is the Problem

2017-11-05 Thread Isiah Meadows
You may be interested in [this][1]. It's actually not that uncommon in
childrens' programming, animation, and other less technical needs for
scripting. Also, consider [Node-RED][2], which is also a visual
platform for the Internet of Things (with a JS core, but you rarely
need to actually dive into JS for most things).

[1]: https://en.wikipedia.org/wiki/Visual_programming_language
[2]: https://nodered.org/
-

Isiah Meadows
m...@isiahmeadows.com

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com


On Sun, Nov 5, 2017 at 8:22 AM, Michael Lewis  wrote:
> Raul-Sebastian Mihăilă just made a post here about some mixin syntax.  I
> didn't read it (sorry).
>
> But, it got me thinking about a concept I've been thinking for years:
> syntax is the problem, and there's a better solution.
>
> If you define syntax as a human <--> computer language (a human-readable and
> computer-readable form of text), you necessarily need a very strictly
> defined syntax.  One missing curly, and you're f'd.
>
> Duh, we all know this.  Hang onto your pants for a second, let's explore an
> alternative.
>
> What if we edited scripts more directly in AST form (abstract syntax tree).
> Developers could implement their own UI to manipulate this AST.  There are
> many, many benefits to this, I'll get to in a second.
>
> First, let's remember what everyone in the JS community is doing right now:
> running their code through transpilers.  (I refuse to do this, that's why
> I'm unemployed - I strongly dislike the concept).  What is a transpiler?
> It's an unofficial middleman that interprets the syntax, converts it to an
> AST, performs transformations, and then returns the AST to syntax form.
>
> Suddenly, scripting in AST form doesn't sound so crazy.
>
> Clearly, you wouldn't be writing JSON.  We would be using a GUI to create
> the AST.  And this is the greatest benefit: moving away from syntax, and
> moving to a GUI.
>
> Then, instead of babel plugins that provide alternative syntax, you could
> have plugins that provide alternative experiences.
>
> What would designing a class look like, if using a GUI?
>
> Click [ create new class ]
> Click [ add new method ]
>
> Or, click the [ extend ] button next to an existing class...
>
> This is the future.  I have to go eat breakfast, but I'd love to discuss
> this future if anyone is interested...
>
> ___
> 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: Web Docs

2017-11-05 Thread Isiah Meadows
Not on the committee, but IMHO that should be up to MDN rather than
TC39. Also, you *could* look at the [meeting notes][1], specifically
the summaries of each meeting, to see what happened. Alternatively,
someone *could* create a centralized resource of what each meeting
decided. (I'd personally do it if I got a Patreon set up and got some
funding to do it, to make up for the lost productivity elsewhere.)

[1]: https://esdiscuss.org/notes
-

Isiah Meadows
m...@isiahmeadows.com

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com


On Sun, Nov 5, 2017 at 7:29 AM, Michael Lewis  wrote:
> tl;dr Maybe there needs to be an official blog?  And/or summarize decisions
> on MDN?
>
> With the advent of transpiling, the state of the ES language is in greater
> flux than ever before.  This group guides the development of the language
> itself.  Then there are the implementers of your specifications.  I won't
> pretend to know how it works, but it's safe to say, "it's like trying to hit
> a moving target."  While standing on a moving platform.
>
> When Andrea Giammarchi just wrote a post here showing an example of
> extending the native Array "class", I wasn't aware that was even
> possible/recommended.
>
> I found an article from 2015 the other day, and scoured at it's age.  "This
> is worthless! Nothing from 2015 is still valid today."  It's very common to
> discover some new syntax, and not really know what it is.  Is it a babel
> plugin?  TypeScript?  ES9000?  Where can I use it?  When should I use it?
>
> If this is the "official" JavaScript Steering Committee, then it would make
> sense that you should produce the authoritative documentation, and publish
> the authoritative announcements/reasoning.
>
> For example, when TC39 decided to remove properties from classes, there
> should have been an announcement.  It seems like many people disagree with
> this decision (myself included).
>
> The MDN web docs are trying to be the go to place for all things web.  Yet,
> I still google, "can i use es6 classes" to find browser compatibility info.
> Because MDN has already dissected "all the things" (they have navigation and
> pages for all the topics you might discuss), documenting certain design
> decisions on their site might make the most sense.  Maybe you just start
> with a TC39 Design Notes sub page that can be added in various places.
>
> We should condense, summarize, and publish the enormously complex work that
> is going on in these back channels.  Basically, extract the most important
> stuff.  Extract the signal from the noise, and share it in an official
> place.
>
> What is this community's stance on documentation?
>
>
> ___
> 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: Definition mixins

2017-11-05 Thread Michał Wadas
Saying "you don't need this if you follow my personal way of doing things"
isn't helpful at all. Especially when these views are *controversial*.

On 5 Nov 2017 4:27 pm, "kai zhu"  wrote:

the problem is that you chose to write the chess program in
javascript, instead of say, python or c#.

why did you choose javascript?  probably because you intend the chess
program to be an online webapp.  mixins, like classes, are inferior to
plain json-objects for webapps.  how do you intend to serialize the
mixin board-state so you can sync it with a friend in an online match?
 the i/o part of a webapp is typically as challenging as the
business-logic of the game itself.

it would be more efficient if you represented the board-state as a
json-object, so it can be easily serailized and shared with other
online players, and use static functions to manipulate the json-data.

here's a functional web-demo of a simple connect4 game using only
json-objects and static functions (in 400 lines of code).

-kai

https://github.com/kaizhu256/node-connect4

```js
/*
 * test.js
 *
 * this file contains the standalone connect-4 game
 *
 * setup instructions
 * 1. save this file as test.js
 * 2. install nodejs
 * 3. run the shell command
 *$ PORT=8081 node test.js
 * 4. open browser to url http://localhost:8081
 * 5. play the connect4 game!
 */



/*jslint
bitwise: true,
browser: true,
maxerr: 8,
maxlen: 96,
node: true,
nomen: true,
regexp: true,
stupid: true
*/
(function () {
'use strict';
var local;



// run shared js-env code - pre-init
(function () {
// init local
local = {};
// init modeJs
local.modeJs = (function () {
try {
return typeof navigator.userAgent === 'string' &&
typeof document.querySelector('body') === 'object' &&
typeof XMLHttpRequest.prototype.open === 'function' &&
'browser';
} catch (errorCaughtBrowser) {
return module.exports &&
typeof process.versions.node === 'string' &&
typeof require('http').createServer === 'function' &&
'node';
}
}());
// init global
local.global = local.modeJs === 'browser'
? window
: global;
local.nop = function () {
/*
 * this function will do nothing
 */
return;
};
// export local
local.global.local = local;
}());



// run shared js-env code - function
(function () {
local.gameStateCreate = function () {
/*
 * this function will create a new game state
 */
var state;
state = {};
state.board = [
// -> rows
[0, 0, 0, 0, 0, 0], // |
[0, 0, 0, 0, 0, 0], // v
[0, 0, 0, 0, 0, 0], //
[0, 0, 0, 0, 0, 0], // c
[0, 0, 0, 0, 0, 0], // o
[0, 0, 0, 0, 0, 0], // l
[0, 0, 0, 0, 0, 0]  // s
];
state.playerCurrent = 1;
state.streakToWin = 4;
return state;
};

local.playerMove = function (state, positionCol) {
/*
 * this function will perform a move
 * by dropping the state.playerCurrent's disc in the given
positionCol,
 * and then checks to see if it wins the game
 */
var colList, ii, positionRow, streak;
if (state.ended) {
state.error = new Error('game ended');
}
if (state.error) {
// debug error
console.error(state.error.stack);
return;
}
if (positionCol === 'random') {
while (true) {
positionCol = Math.floor(Math.random() *
state.board.length);
colList = state.board[positionCol] || [];
if (colList[colList.length - 1] === 0) {
break;
}
}
}
state.positionCol = positionCol;
colList = state.board[positionCol] || [];
// naive algorithm to deposit disc in the last unfilled
positionRow in colList
for (ii = 0; ii < colList.length; ii += 1) {
if (colList[ii] === 0) {
positionRow = ii;
colList[positionRow] = state.playerCurrent;
// debug board
console.log(state.board.join('\n'));
break;
}
}
if (positionRow === undefined) {
state.error = new Error('invalid move');
// debug error
console.error(state.error.stack);
return;
}
// naive 

Re: Definition mixins

2017-11-05 Thread Raul-Sebastian Mihăilă
On Sun, Nov 5, 2017 at 5:27 PM, kai zhu  wrote:

> the problem is that you chose to write the chess program in
> javascript, instead of say, python or c#.
>

Kai, you're off-topic. The topic is mixins, not chess games. Please refrain
from disrupting this thread.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Can `new` be optional?

2017-11-05 Thread Andrea Giammarchi
oldie but goldie ?

```js
Object.defineProperty(
  Function.prototype,
  'new',
  {
configurable: true,
value(...args) {
  return new this(...args);
}
  }
);
```





On Sun, Nov 5, 2017 at 11:28 AM, Oriol _  wrote:

> > Why can't `new` be optional?
>
> When you call a function, you are using the internal [[Call]] method. When
> you use the `new` operator, it's the internal [[Construct]] method.
>
> They are different things, so IMO avoiding `new` when you are
> instantiating is bad practice.
>
> But if you really want to avoid `new` when using ES6 `class` syntax, you
> can use proxies, e.g.
>
> ```js
> let MyClass = new Proxy(class MyClass {
>   constructor(arg) { this.arg = arg; }
> }, {
>   apply: (target, thisArg, args) => Reflect.construct(target, args)
> });
> MyClass(1); // { arg: 1 }
> new MyClass(2); // { arg: 2 }
> ```
>
> --Oriol
>
> ___
> 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


Definition mixins

2017-11-05 Thread Raul-Sebastian Mihăilă
Actually the mix obj must be extensible but must be an exotic object so
that it's extended only through the mixin mechanism.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Definition mixins

2017-11-05 Thread kai zhu
the problem is that you chose to write the chess program in
javascript, instead of say, python or c#.

why did you choose javascript?  probably because you intend the chess
program to be an online webapp.  mixins, like classes, are inferior to
plain json-objects for webapps.  how do you intend to serialize the
mixin board-state so you can sync it with a friend in an online match?
 the i/o part of a webapp is typically as challenging as the
business-logic of the game itself.

it would be more efficient if you represented the board-state as a
json-object, so it can be easily serailized and shared with other
online players, and use static functions to manipulate the json-data.

here's a functional web-demo of a simple connect4 game using only
json-objects and static functions (in 400 lines of code).

-kai

https://github.com/kaizhu256/node-connect4

```js
/*
 * test.js
 *
 * this file contains the standalone connect-4 game
 *
 * setup instructions
 * 1. save this file as test.js
 * 2. install nodejs
 * 3. run the shell command
 *$ PORT=8081 node test.js
 * 4. open browser to url http://localhost:8081
 * 5. play the connect4 game!
 */



/*jslint
bitwise: true,
browser: true,
maxerr: 8,
maxlen: 96,
node: true,
nomen: true,
regexp: true,
stupid: true
*/
(function () {
'use strict';
var local;



// run shared js-env code - pre-init
(function () {
// init local
local = {};
// init modeJs
local.modeJs = (function () {
try {
return typeof navigator.userAgent === 'string' &&
typeof document.querySelector('body') === 'object' &&
typeof XMLHttpRequest.prototype.open === 'function' &&
'browser';
} catch (errorCaughtBrowser) {
return module.exports &&
typeof process.versions.node === 'string' &&
typeof require('http').createServer === 'function' &&
'node';
}
}());
// init global
local.global = local.modeJs === 'browser'
? window
: global;
local.nop = function () {
/*
 * this function will do nothing
 */
return;
};
// export local
local.global.local = local;
}());



// run shared js-env code - function
(function () {
local.gameStateCreate = function () {
/*
 * this function will create a new game state
 */
var state;
state = {};
state.board = [
// -> rows
[0, 0, 0, 0, 0, 0], // |
[0, 0, 0, 0, 0, 0], // v
[0, 0, 0, 0, 0, 0], //
[0, 0, 0, 0, 0, 0], // c
[0, 0, 0, 0, 0, 0], // o
[0, 0, 0, 0, 0, 0], // l
[0, 0, 0, 0, 0, 0]  // s
];
state.playerCurrent = 1;
state.streakToWin = 4;
return state;
};

local.playerMove = function (state, positionCol) {
/*
 * this function will perform a move
 * by dropping the state.playerCurrent's disc in the given positionCol,
 * and then checks to see if it wins the game
 */
var colList, ii, positionRow, streak;
if (state.ended) {
state.error = new Error('game ended');
}
if (state.error) {
// debug error
console.error(state.error.stack);
return;
}
if (positionCol === 'random') {
while (true) {
positionCol = Math.floor(Math.random() *
state.board.length);
colList = state.board[positionCol] || [];
if (colList[colList.length - 1] === 0) {
break;
}
}
}
state.positionCol = positionCol;
colList = state.board[positionCol] || [];
// naive algorithm to deposit disc in the last unfilled
positionRow in colList
for (ii = 0; ii < colList.length; ii += 1) {
if (colList[ii] === 0) {
positionRow = ii;
colList[positionRow] = state.playerCurrent;
// debug board
console.log(state.board.join('\n'));
break;
}
}
if (positionRow === undefined) {
state.error = new Error('invalid move');
// debug error
console.error(state.error.stack);
return;
}
// naive algorithm to check for win condition in the column
// e.g.
// [
// -> rows
// [1, 1, 1, 1, 0, 0], // |
// [2, 2, 2, 0, 0, 0], // v
// [0, 0, 

Definition mixins

2017-11-05 Thread Raul-Sebastian Mihăilă
Also, in the same context, for different mixin associated objects there
will be different mix objects:

```js
function F() {
  const obj = {};
  const obj2 = {};

  mixin obj, mixin1;
  mixin obj2, mixin2;
}

function mixin1() {
  return (obj, mix) => {};
}

function mixin2() {
  return (obj, mix) => {};
}
```

The mix argument that the mixin function created by mixin2 receives will be
different from the one received by the mixin function created by mixin1
because obj1 !== obj2.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Can `new` be optional?

2017-11-05 Thread Oriol _
> Why can't `new` be optional?

When you call a function, you are using the internal [[Call]] method. When you 
use the `new` operator, it's the internal [[Construct]] method.

They are different things, so IMO avoiding `new` when you are instantiating is 
bad practice.

But if you really want to avoid `new` when using ES6 `class` syntax, you can 
use proxies, e.g.

```js
let MyClass = new Proxy(class MyClass {
  constructor(arg) { this.arg = arg; }
}, {
  apply: (target, thisArg, args) => Reflect.construct(target, args)
});
MyClass(1); // { arg: 1 }
new MyClass(2); // { arg: 2 }
```

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


Definition mixins

2017-11-05 Thread Raul-Sebastian Mihăilă
One issue that just occurred to me is that we want different families of
mixin functions to have access to different mix objects, so that one family
doesn't have access to mixin functions from another family (since they're
private and the constructor must decide what private data shares with the
mixin functions). So different mix object could be created for different
families based on the reference's base value (by reference I mean the
reference that is used to specify the mixin function).

```js
mixin obj, mixinModule.func1;
mixin obj, mixinModule.func2;
mixin obj, func3;
```

Here func1 and func2 will use the same mix object and func3 will have
another mix object.

Another solution would be, since normally mixin functions are imported from
other modules, to have the source module of the mixin function as the
grouping key for the mixin functions, even if the base value of the
reference is an environment record (like in func3's case). If the mixin
functions belong to the current module it's fine for them to share the
private state.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Syntax is the Problem

2017-11-05 Thread Michael Lewis
Raul-Sebastian Mihăilă just made a post here about some mixin syntax.  I
didn't read it (sorry).

But, it got me thinking about a concept I've been thinking for years:  *syntax
is the problem*, and there's a better solution.

If you define syntax as a human <--> computer language (a human-readable
and computer-readable form of text), you necessarily need a very strictly
defined syntax.  One missing curly, and you're f'd.

Duh, we all know this.  Hang onto your pants for a second, let's explore an
alternative.

What if we edited scripts more directly in AST form (abstract syntax
tree).  Developers could implement their own UI to manipulate this AST.
There are many, many benefits to this, I'll get to in a second.

First, let's remember what everyone in the JS community is doing right
now:  running their code through transpilers.  (I refuse to do this, that's
why I'm unemployed - I strongly dislike the concept).  What is a
transpiler?  It's an unofficial middleman that interprets the syntax,
converts it to an AST, performs transformations, and then returns the AST
to syntax form.

Suddenly, scripting in AST form doesn't sound so crazy.

Clearly, you wouldn't be writing JSON.  We would be using a GUI to create
the AST.  And this is the greatest benefit: moving away from *syntax*, and
moving to a GUI.

Then, instead of babel plugins that provide alternative *syntax*, you could
have plugins that provide alternative *experiences.*

What would designing a class look like, if using a GUI?

   1. Click [ create new class ]
   2. Click [ add new method ]

Or, click the [ extend ] button next to an existing class...

This is the future.  I have to go eat breakfast, but I'd love to discuss
this future if anyone is interested...
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Definition mixins

2017-11-05 Thread Raul-Sebastian Mihăilă
I've been successfully experimenting with a kind of mixins which is
different from the naive mixin solution (for instance based on
Object.assign) and from functional mixins (
https://medium.com/javascript-scene/functional-mixins-composing-software-ffb66d5e731c).
I call them definition mixins.

The reason I'm bringing this up is that the definition mixins solution is
verbose and custom syntax would be useful to simplify things.

Using traditional functions we can create constructors that hold private
state. The main difference between definition mixins and the other ones is
that the mixins share private state with the context where they are used.
In this way, they are intimately connected to the context where the object
is created. It's important to note that the constructor will choose what
private state to share with the mixins.

Other differences:
- you don't get the gorilla-banana problem
- you don't get property collisions at all (unlike the other mixins where
the last object always wins)
- beside sharing private state, another advantage is that you explicitly
pick the functions that you want to mix in, so it's clear what the object's
structure is by simply looking at its definition (which can be useful in a
dynamic language like js).

Beside sharing private state, the other issues with the other kinds of
mixins can be solved by using specific APIs with which you explicitly list
the functions you're interested in.

Example:
Let's say we have a game of chess. We have a game board that is used to
play the game and a building board that is used to create specific
positions and then start a game from those positions. The game board and
the building board are similar because they have similar state and logic to
update that state (for instance whether the position is checkmate,
stalemate etc.) because we want to create a game board from a building
board and vice versa. They are also different because a simple board will
have a move function that moves a piece and updates the state of the board.
A possible move is en passant. You can not perform en passant in a building
board, because the building board is not used for playing the game. The
building board has a deletePiece function that is used to remove any number
of pieces from the board anytime. The game board doesn't have such a
function because the only way a piece can be removed during a game is by
following the rules of chess. The game board also handles promoting pawns,
while the building board doesn't.

```js
// board file
import * as boardMixin from '...';

function Board({board: fromBoard}) {
  const mix = {
kings: {},
currentMove
  };
  let promotingPawn = null;
  const board = boardMixin.create();

  board.currentSide = null;
  board.isPromoting = false;
  board.isCheckmate = false;
  board.isStalemate = false;
  board.isDraw = false;

  const isSafeMove = mix.isSafeMove = boardMixin.isSafeMove(mix);
  const setBoardResolution = mix.setBoardResolution =
boardMixin.setBoardResolution(board, mix);

  board.isSquareAttacked = boardMixin.isSquareAttacked(board);
  board.getPiece = boardMixin.getPiece(board);

  board.move = (piece, x, y) => {
// ...
if (!isSafeMove(piece, x, y)) {
  return false;
}

setBoardResolution();
  };

  // ...
}
```

---

```js
// building-board file
import * as boardMixin from '...';

function BuildingBoard({board: fromBoard}) {
  const mix = {
kings: {},
currentMove: null
  };
  const board = boardMixin.create();

  board.currentSide = null;
  board.isCheckmate = false;
  board.isStalemate = false;
  board.isDraw = false;

  const setBoardResolution = mix.setBoardResolution =
boardMixin.setBoardResolution(board, mix);

  board.getPiece = boardMixin.getPiece(board);

  board.isBoardPlayable = () => {
// ...
  };

  board.deletePiece = (piece) => {
// ...

setBoardResolution();
  };
}
```

---

```js
// board-mixin file
// mixin functions:
const isSafeMove = (mix) =>
  (piece, x, y) => {
// ...
  };

const setBoardResolution = (board, mix) =>
  () => {
// ...
board.isCheckmate = true;
  };

// ...
```

In this example we're creating mixin functions that become public or
private methods in the constructor. The mix object is used to hold the
mixin functions as a mixin function might want to use another mixin
function. Also, in our example we're also holding in the mix object the
private state that we wish to share with the mixin functions. The board
object is an array of arrays and because we use it in the mixin functions
we need to make sure that it's created before the mixin functions are mixed
into the constructor. Mixin functions such as isSafeMove are also assigned
to consts because we want to easily call them in the constructor, without
having to use the mix object.

This is verbose. It would be niced if we could:
- create bindings for the mixin functions in the constructor more easily
- add the mixin functions to the mix object more easily
- create the board 

Re: Can `new` be optional?

2017-11-05 Thread Michael Lewis
Is there a technical limitation, or just an opinion?

If I call an ES6 `class MyClass {}` without new:  `MyClass()`, it throws.
Just change this bit to do whatever `new` was supposed to do.  Problem
solved?

On Sun, Nov 5, 2017 at 6:01 AM, Michał Wadas  wrote:

> This was covered by "call constructor" proposal, but unfortunately, it was
> withdrawn.
>
> https://github.com/tc39/ecma262/blob/master/workingdocs/callconstructor.md
>
> Status: "Withdrawn: can be solved with decorators" -
> https://github.com/tc39/proposals/blob/master/inactive-proposals.md
>
> On 5 Nov 2017 12:55 pm, "Michael Lewis"  wrote:
>
>> Why can't `new` be optional?
>>
>> I found this thread, https://esdiscuss.org/topic/ob
>> soleting-the-new-keyword, but it's so long (and 9 years old), I didn't
>> read much of it.  Can someone summarize the current status of this decision?
>>
>> On a side note, it seems the ES Steering Committee needs a wiki - a place
>> to document important decisions.  I feel like the MDN web docs would be a
>> good place to put all levels of documentation.  I'm going to make a new
>> thread about docs, it's so important...
>>
>>
>> Anyway, in my ES5 "classes", I use an `if (!(this instanceof Class))
>> return new Class()` (similar to what jQuery does) to avoid having to use
>> `new`.  I feel like there should be a way to build this into the language.
>>
>> I have a `View()` class that is invoked a lot:
>>
>> ```
>> View().append({
>> one: View(...),
>> two: View(View(...), View(...))
>> });
>> ```
>>
>> And, being forced to write `new View()` every time is actually the only
>> reason why I won't switch to native classes, at the moment.
>>
>>
>> ___
>> 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


Web Docs

2017-11-05 Thread Michael Lewis
tl;dr Maybe there needs to be *an official blog*?  And/or summarize
decisions on MDN?

With the advent of transpiling, the state of the ES language is in greater
flux than ever before.  This group guides the development of the language
itself.  Then there are the implementers of your specifications.  I won't
pretend to know how it works, but it's safe to say, "it's like trying to
hit a moving target."  While standing on a moving platform.

When Andrea Giammarchi just wrote a post here showing an example of
extending the native Array "class", I wasn't aware that was even
possible/recommended.

I found an article from 2015 the other day, and scoured at it's age.  "This
is worthless! Nothing from 2015 is still valid today."  It's very common to
discover some new syntax, and not really know what it is.  Is it a babel
plugin?  TypeScript?  ES9000?  Where can I use it?  When should I use it?

If this is the "official" JavaScript Steering Committee, then it would make
sense that you should produce the authoritative documentation, and publish
the authoritative announcements/reasoning.

For example, when TC39 decided to remove properties from classes, there
should have been an announcement.  It seems like many people disagree with
this decision (myself included).

The MDN web docs are trying to be the go to place for all things web.  Yet,
I still google, "can i use es6 classes" to find browser compatibility
info.  Because MDN has already dissected "all the things" (they have
navigation and pages for all the topics you might discuss), documenting
certain design decisions on their site might make the most sense.  Maybe
you just start with a TC39 Design Notes sub page that can be added in
various places.

We should condense, summarize, and publish the enormously complex work that
is going on in these back channels.  Basically, extract the most important
stuff.  Extract the signal from the noise, and share it in an official
place.

What is this community's stance on documentation?
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Can `new` be optional?

2017-11-05 Thread Michał Wadas
This was covered by "call constructor" proposal, but unfortunately, it was
withdrawn.

https://github.com/tc39/ecma262/blob/master/workingdocs/callconstructor.md

Status: "Withdrawn: can be solved with decorators" -
https://github.com/tc39/proposals/blob/master/inactive-proposals.md

On 5 Nov 2017 12:55 pm, "Michael Lewis"  wrote:

> Why can't `new` be optional?
>
> I found this thread, https://esdiscuss.org/topic/
> obsoleting-the-new-keyword, but it's so long (and 9 years old), I didn't
> read much of it.  Can someone summarize the current status of this decision?
>
> On a side note, it seems the ES Steering Committee needs a wiki - a place
> to document important decisions.  I feel like the MDN web docs would be a
> good place to put all levels of documentation.  I'm going to make a new
> thread about docs, it's so important...
>
>
> Anyway, in my ES5 "classes", I use an `if (!(this instanceof Class))
> return new Class()` (similar to what jQuery does) to avoid having to use
> `new`.  I feel like there should be a way to build this into the language.
>
> I have a `View()` class that is invoked a lot:
>
> ```
> View().append({
> one: View(...),
> two: View(View(...), View(...))
> });
> ```
>
> And, being forced to write `new View()` every time is actually the only
> reason why I won't switch to native classes, at the moment.
>
>
> ___
> 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


Can `new` be optional?

2017-11-05 Thread Michael Lewis
Why can't `new` be optional?

I found this thread, https://esdiscuss.org/topic/obsoleting-the-new-keyword,
but it's so long (and 9 years old), I didn't read much of it.  Can someone
summarize the current status of this decision?

On a side note, it seems the ES Steering Committee needs a wiki - a place
to document important decisions.  I feel like the MDN web docs would be a
good place to put all levels of documentation.  I'm going to make a new
thread about docs, it's so important...


Anyway, in my ES5 "classes", I use an `if (!(this instanceof Class)) return
new Class()` (similar to what jQuery does) to avoid having to use `new`.  I
feel like there should be a way to build this into the language.

I have a `View()` class that is invoked a lot:

```
View().append({
one: View(...),
two: View(View(...), View(...))
});
```

And, being forced to write `new View()` every time is actually the only
reason why I won't switch to native classes, at the moment.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss