Definition mixins

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

Definition mixins

Raul-Sebastian Mihăilă
I wrote a first draft of the spec for the proposal (https://github.com/raulsebastianmihaila/ecma262-definition-mixins-proposal). In some cases I'm not certain about the accuracy of the spec and I also cut the corners in a few places. There are 2 versions. The second version only contains the differences from the first version. Version 1 is simpler. Version 2 uses indirect bindings in a mixin function provider call and these semantics don't exist in the language. I didn't try to spec them as I thought it would be challenging (probably involving creating a new kind of function). If this is not pragmatic it's fine, version 1 doesn't have indirect bindings. I like version 2 a bit more, but version 1 would work as well.

Any feedback from people from TC39 or people interested in mixins is appreciated.

Compare the following two fragments, one with current ES syntax/semantics, and the other one with the mixin syntax/semantics (from the first simpler version of the spec).

```js
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);
```

```js
const mixState = {
  kings: {},
  currentMove
};
let promotingPawn = null;
const board = boardMixin.create();

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

mixin board:
  boardMixin.isSafeMove,
  boardMixin.setBoardResolution:
    mixState;

mixin on board:
  boardMixin.isSquareAttacked,
  boardMixin.getPiece;
```

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

Re: Definition mixins

T.J. Crowder-2
On Mon, Nov 13, 2017 at 8:45 AM, Raul-Sebastian Mihăilă <[hidden email]> wrote:
>
> I wrote a first draft of the spec for the proposal...

Could you add a "Motivations" section outlining why this is needed and what alternatives currently exist without new syntax?

Separately, without yet having delved into the details, various parts of the "without mixins" code look suspect, for example:

```js
const isSafeMove = mix.isSafeMove = boardMixin.isSafeMove(mix);
```

That *calls* the `boardMixin.isSafeMove` function, passing it the `mix` constant, and assigns its return value to `mix.isSafeMove` and a new constant `isSafeMove` (which confusingly doesn't seem to be used anywhere). Should it really be *calling* the function? Not binding or something?

-- T.J. Crowder

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

Fwd: Definition mixins

Raul-Sebastian Mihăilă
On Mon, Nov 13, 2017 at 10:54 AM, T.J. Crowder <[hidden email]> wrote:

Could you add a "Motivations" section outlining why this is needed and what alternatives currently exist without new syntax?


It would be indeed worth adding such a section in the proposal, but for now please take a look at the first message in this thread in which I do mention why this syntax is useful and current alternatives.
 
Separately, without yet having delved into the details, various parts of the "without mixins" code look suspect, for example:

```js
const isSafeMove = mix.isSafeMove = boardMixin.isSafeMove(mix);
```

That *calls* the `boardMixin.isSafeMove` function, passing it the `mix` constant, and assigns its return value to `mix.isSafeMove` and a new constant `isSafeMove` (which confusingly doesn't seem to be used anywhere). Should it really be *calling* the function? Not binding or something?

-- T.J. Crowder

Please do delve into the details (especially the first message in this thread). The first message shows how the mix object is used. Without mixins syntax, the mix object has two purposes, it holds the mixin functions that are provided by mixin function providers so that you can call a mixin function in another mixin function. This mix object is passed to the mixin function providers, so that the mixin functions that they create can use the object. However, since an essential part of this proposal is the ability to share private state with the mixin functions, the mix object also contains the private state to be shared.

The reason the `isSafeMove` constant is created is to be able to easily call the function in the current context, without having to use the mix object. It's a nice to have. The mixin syntax not only makes this possible, but it also provides the separation between holding the mixin functions in an object so that they are accessible in the mixin functions themselves and sharing whatever private data needs to be shared with the mixin functions. This separation would have also been possible without the mixin syntax. However, the syntax is much simpler with this proposal: the constant binding is created, or the function can become a public method of the object, you don't need to create and handle the mix object and this also works with private fields in a class context. Also, the second version of the proposal is based on the possibly controversial idea of indirect bindings in a function context.



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

Re: Definition mixins

Bob Myers
You should review the TypeScript approach to mixins: https://www.typescriptlang.org/docs/handbook/mixins.html.

But more generally, mixins are a very specific, opinionated OO design pattern. They are probably misused more often than not. If you think that big class hierarchies were brittle and hard to maintain, just wait until you include mixins. There are many, many alternatives to modeling things like "can move more than one square at a time in some direction", and most of them are, at least in my opinion, superior to mixins. It is also not too hard to make the case that mixins are somewhere between difficult and impossible to implement properly in a language which doesn't have proper built-in support--the fundamental notion of prototypes in JS, which underlies its classes, can be considered mixin-hostile.

Bob



On Mon, Nov 13, 2017 at 3:09 PM, Raul-Sebastian Mihăilă <[hidden email]> wrote:
On Mon, Nov 13, 2017 at 10:54 AM, T.J. Crowder <[hidden email]> wrote:

Could you add a "Motivations" section outlining why this is needed and what alternatives currently exist without new syntax?


It would be indeed worth adding such a section in the proposal, but for now please take a look at the first message in this thread in which I do mention why this syntax is useful and current alternatives.
 
Separately, without yet having delved into the details, various parts of the "without mixins" code look suspect, for example:

```js
const isSafeMove = mix.isSafeMove = boardMixin.isSafeMove(mix);
```

That *calls* the `boardMixin.isSafeMove` function, passing it the `mix` constant, and assigns its return value to `mix.isSafeMove` and a new constant `isSafeMove` (which confusingly doesn't seem to be used anywhere). Should it really be *calling* the function? Not binding or something?

-- T.J. Crowder

Please do delve into the details (especially the first message in this thread). The first message shows how the mix object is used. Without mixins syntax, the mix object has two purposes, it holds the mixin functions that are provided by mixin function providers so that you can call a mixin function in another mixin function. This mix object is passed to the mixin function providers, so that the mixin functions that they create can use the object. However, since an essential part of this proposal is the ability to share private state with the mixin functions, the mix object also contains the private state to be shared.

The reason the `isSafeMove` constant is created is to be able to easily call the function in the current context, without having to use the mix object. It's a nice to have. The mixin syntax not only makes this possible, but it also provides the separation between holding the mixin functions in an object so that they are accessible in the mixin functions themselves and sharing whatever private data needs to be shared with the mixin functions. This separation would have also been possible without the mixin syntax. However, the syntax is much simpler with this proposal: the constant binding is created, or the function can become a public method of the object, you don't need to create and handle the mix object and this also works with private fields in a class context. Also, the second version of the proposal is based on the possibly controversial idea of indirect bindings in a function context.



_______________________________________________
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: Definition mixins

Raul-Sebastian Mihăilă

On Mon, Nov 13, 2017 at 1:54 PM, Bob Myers <[hidden email]> wrote:
You should review the TypeScript approach to mixins: https://www.typescriptlang.org/docs/handbook/mixins.html.

This seems very similar to the naive approach based on Object.assign that I mention in the first message of this thread. Please see the disadvantages that I mention there and also note that this approach doesn't provide the ability to share private state.


But more generally, mixins are a very specific, opinionated OO design pattern. They are probably misused more often than not. If you think that big class hierarchies were brittle and hard to maintain, just wait until you include mixins.

Could you please provide some more details? The advantages of my approach to mixins in comparison to other approaches that I mentioned in the first message also apply in comparison to inheritance.
 
There are many, many alternatives to modeling things like "can move more than one square at a time in some direction", and most of them are, at least in my opinion, superior to mixins.

The chess example is just an example. What mixins achieve in general is sharing a partial definition of a concept in multiple places. Can you please mention a few of the many, many superior alternatives to achieve this (please note I'm also interested in using private state)?
 
It is also not too hard to make the case that mixins are somewhere between difficult and impossible to implement properly in a language which doesn't have proper built-in support--the fundamental notion of prototypes in JS, which underlies its classes, can be considered mixin-hostile.


Did you take a look at the spec I provided? The first version is based 100% on concepts and mechanisms already used in Ecma262. 

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