Concise Method Binding

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

Concise Method Binding

JD Isaacks
Considering the proposals for both concise methods and the bind operator I think it would be a great addition to be able to use them together.

I am already seeing a lot of this:

class Foo {
  bar = () => {
    // bound
  }
  buz() {
    // unbound
  }
}

I think having the bind operator with a concise method makes things more uniform:

class Foo {
  ::bar() {
    // bound
  }
  buz() {
    // unbound
  }
}

This would also allow for this to be using on object literals:

let foo = {
  ::bar() {
    // bound
  }
  buz() {
    // unbound
  }
}

This would also make using recursion with concise functions feasible:

let fibonacci = {
  ::at(n) {
    if (n < 2) {
      return n;
    }
    return this.at(n-1) + this.at(n-2);
  }
}

fibonacci.at(7); // 13

I am looking for a champion for this feature. Anybody interested?

Thanks,
JD Isaacks

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

Re: Concise Method Binding

Jordan Harband
In your first example, the arrow function's "this" would be the "this" of the context the "class" is defined in - it wouldn't be bound at all. Can you point me to an example of where that example "bar" is a function bound to the instance?

On Mon, Nov 9, 2015 at 5:45 PM, JD Isaacks <[hidden email]> wrote:
Considering the proposals for both concise methods and the bind operator I think it would be a great addition to be able to use them together.

I am already seeing a lot of this:

class Foo {
  bar = () => {
    // bound
  }
  buz() {
    // unbound
  }
}

I think having the bind operator with a concise method makes things more uniform:

class Foo {
  ::bar() {
    // bound
  }
  buz() {
    // unbound
  }
}

This would also allow for this to be using on object literals:

let foo = {
  ::bar() {
    // bound
  }
  buz() {
    // unbound
  }
}

This would also make using recursion with concise functions feasible:

let fibonacci = {
  ::at(n) {
    if (n < 2) {
      return n;
    }
    return this.at(n-1) + this.at(n-2);
  }
}

fibonacci.at(7); // 13

I am looking for a champion for this feature. Anybody interested?

Thanks,
JD Isaacks

_______________________________________________
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: Concise Method Binding

Bergi
Jordan Harband schrieb:

 > JD Isaacks <[hidden email]> wrote:
 >
 >> class Foo {
 >>    bar = () => {
 >>      // bound
 >>    }
 >>    buz() {
 >>      // unbound
 >>    }
 >> }
> In your first example, the arrow function's "this" would be the "this" of
> the context the "class" is defined in - it wouldn't be bound at all.

No, the methods defined with "=" are automatically moved into the
constructor, so that they are created once for each new instance. `this`
in the arrow function would in fact be bound to the instance.

It's indeed super-confusing to "declare" such methods right inside the
`class` though, that's why I'm really opposing that proposal
(https://github.com/jeffmo/es-class-static-properties-and-fields).

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

Re: Re: Concise Method Binding

JD Isaacks
In reply to this post by JD Isaacks

Bergi, I agree and I think this proposal negates the need for assigning methods like that.


On Mon, Nov 9, 2015 at 9:46 PM, John Isaacks <[hidden email]> wrote:
Bergi, I agree and I think this proposal negates the need for assigning methods like that.


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

Re: Concise Method Binding

Rick Waldron
In reply to this post by JD Isaacks


On Mon, Nov 9, 2015 at 8:45 PM JD Isaacks <[hidden email]> wrote:
Considering the proposals for both concise methods and the bind operator I think it would be a great addition to be able to use them together.

I am already seeing a lot of this:

class Foo {
  bar = () => {
    // bound
  }
  buz() {
    // unbound
  }
}


Can you clarify what this is, because it's not valid ES6 code. Also, "bound" and "unbound" in what sense? In `buz`, the `this` object will be the instance of Foo from which it's called. 

Rick

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

Re: Concise Method Binding

Isiah Meadows-2

It's using an ES7 proposal, and it's a method bound to the instance.


On Tue, Nov 10, 2015, 18:58 Rick Waldron <[hidden email]> wrote:
On Mon, Nov 9, 2015 at 8:45 PM JD Isaacks <[hidden email]> wrote:
Considering the proposals for both concise methods and the bind operator I think it would be a great addition to be able to use them together.

I am already seeing a lot of this:

class Foo {
  bar = () => {
    // bound
  }
  buz() {
    // unbound
  }
}


Can you clarify what this is, because it's not valid ES6 code. Also, "bound" and "unbound" in what sense? In `buz`, the `this` object will be the instance of Foo from which it's called. 

Rick
_______________________________________________
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: Concise Method Binding

Rick Waldron


On Tue, Nov 10, 2015 at 6:59 PM Isiah Meadows <[hidden email]> wrote:

It's using an ES7 proposal, and it's a method bound to the instance.


Rick

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

Re: Re: Concise Method Binding

JD Isaacks
In reply to this post by JD Isaacks
So far all the comments have been regarding my first example using ES7 class properties proposal. No one has actually even mentioned the the part I am proposing. Is my explanation just poor?

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

Re: Re: Concise Method Binding

Andrea Giammarchi-2

On Wed, Nov 11, 2015 at 2:10 PM, JD Isaacks <[hidden email]> wrote:
So far all the comments have been regarding my first example using ES7 class properties proposal. No one has actually even mentioned the the part I am proposing. Is my explanation just poor?

_______________________________________________
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: Re: Concise Method Binding

JD Isaacks
In reply to this post by JD Isaacks
Andrea, Sort of. I am talking about adding an additional place where that operator `::` can be used -- with concise methods.

Currently they cannot be used in the way I described above but I think there are several reasons why it makes sense.

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

Re: Re: Concise Method Binding

Andrea Giammarchi-2
Just my thoughts, I wouldn't put any self-bound thing in the class and rather improve that `::` proposal so that whenever you `obj::method` it creates a uniquely bound callback so that `obj::method === obj::method` and at that point whenever you need to export, pass, or use such method you just `obj::method` or `obj::method()` or `let method = obj::method` and bring the pattern whenever it's needed instead of being slightly different per each "place" (class rather than objects)

That would make it lazy, usable for events (in order to be able to also remove them) and easily transpilable for smoother migration.

Having `class A { ::method() {} }` feels like somebody is playing too much with the protoype or "accidentally" polluting the constructor

Regards


On Wed, Nov 11, 2015 at 2:50 PM, JD Isaacks <[hidden email]> wrote:
Andrea, Sort of. I am talking about adding an additional place where that operator `::` can be used -- with concise methods.

Currently they cannot be used in the way I described above but I think there are several reasons why it makes sense.

_______________________________________________
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: Re: Concise Method Binding

JD Isaacks
I think what you are suggesting already exists with `::obj.method` which evaluates to `obj.method.bind(obj)` 

However, this creates a new function each time so `::obj.method !== ::obj.method`, not sure how `::obj.method === ::obj.method` would work.

I sort of agree with you that using it that way would be preferred. However if the community wants bound methods attached to objects, there is currently no way to do that with an object literal.

You would have to do something like:

```
let obj = {};
obj.method = function(){}.bind(obj);
```

With my proposal you can.

```
let obj = { ::method(){} };
```




On Wed, Nov 11, 2015 at 10:20 AM, Andrea Giammarchi <[hidden email]> wrote:
Just my thoughts, I wouldn't put any self-bound thing in the class and rather improve that `::` proposal so that whenever you `obj::method` it creates a uniquely bound callback so that `obj::method === obj::method` and at that point whenever you need to export, pass, or use such method you just `obj::method` or `obj::method()` or `let method = obj::method` and bring the pattern whenever it's needed instead of being slightly different per each "place" (class rather than objects)

That would make it lazy, usable for events (in order to be able to also remove them) and easily transpilable for smoother migration.

Having `class A { ::method() {} }` feels like somebody is playing too much with the protoype or "accidentally" polluting the constructor

Regards


On Wed, Nov 11, 2015 at 2:50 PM, JD Isaacks <[hidden email]> wrote:
Andrea, Sort of. I am talking about adding an additional place where that operator `::` can be used -- with concise methods.

Currently they cannot be used in the way I described above but I think there are several reasons why it makes sense.

_______________________________________________
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: Re: Concise Method Binding

Andrea Giammarchi-2
Yeah, I've got that, my point is that whenever you need it you just `obj::method`

Your example indeed says that currently the proposal is that `obj::method` is similar to `obj.method.bind(obj)` which is indeed always different and indeed you want something that makes method always the same/unique bound one, which I believe is universally the preferred way.

What are two different bound of the same method useful for? Pretty much nothing, IMHO, while having a shortcut to lazily obtain a single bound version of that method for that object can be useful in many ways, as example `obj.on('event', anotherObj::method)` where it's always possible at that point to `obj.removeListener('event', anotherObj::method)` in case its needed.

Having a shortcut that all it does is replace something already short to write like a `.bind` feels to me like a missed opportunity.

Moreover, with this improvement you won't need/care to have self-bound methods at all

```js
let obj = { method(){} };

// and whenever needed you use
obj::method;
```

Hope my POV is more clear now.

Regards









On Wed, Nov 11, 2015 at 4:01 PM, JD Isaacks <[hidden email]> wrote:
I think what you are suggesting already exists with `::obj.method` which evaluates to `obj.method.bind(obj)` 

However, this creates a new function each time so `::obj.method !== ::obj.method`, not sure how `::obj.method === ::obj.method` would work.

I sort of agree with you that using it that way would be preferred. However if the community wants bound methods attached to objects, there is currently no way to do that with an object literal.

You would have to do something like:

```
let obj = {};
obj.method = function(){}.bind(obj);
```

With my proposal you can.

```
let obj = { ::method(){} };
```




On Wed, Nov 11, 2015 at 10:20 AM, Andrea Giammarchi <[hidden email]> wrote:
Just my thoughts, I wouldn't put any self-bound thing in the class and rather improve that `::` proposal so that whenever you `obj::method` it creates a uniquely bound callback so that `obj::method === obj::method` and at that point whenever you need to export, pass, or use such method you just `obj::method` or `obj::method()` or `let method = obj::method` and bring the pattern whenever it's needed instead of being slightly different per each "place" (class rather than objects)

That would make it lazy, usable for events (in order to be able to also remove them) and easily transpilable for smoother migration.

Having `class A { ::method() {} }` feels like somebody is playing too much with the protoype or "accidentally" polluting the constructor

Regards


On Wed, Nov 11, 2015 at 2:50 PM, JD Isaacks <[hidden email]> wrote:
Andrea, Sort of. I am talking about adding an additional place where that operator `::` can be used -- with concise methods.

Currently they cannot be used in the way I described above but I think there are several reasons why it makes sense.

_______________________________________________
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: Re: Concise Method Binding

JD Isaacks
Yes your point of view is more clear now, I like this is a lot.

But I do not know how that would be transpiled or what the desugared version would look like. However, that would be awesome as you described.

A thing to note. You keep using `obj::method` which is different from `::object.method` the former is when method is not already attached to the object, the later is for then it is.

An example:

```
let foo = function(){};
let bar = {};

bar::foo // foo.bind(bar);
```

verses

```
let bar = { foo(){} };

::foo.bar // foo.bar.bind(foo);
```

I think both cases theoretically would be awesome to work as you described. Just fuzzy on how it would look underneath.

On Wed, Nov 11, 2015 at 11:14 AM, Andrea Giammarchi <[hidden email]> wrote:
Yeah, I've got that, my point is that whenever you need it you just `obj::method`

Your example indeed says that currently the proposal is that `obj::method` is similar to `obj.method.bind(obj)` which is indeed always different and indeed you want something that makes method always the same/unique bound one, which I believe is universally the preferred way.

What are two different bound of the same method useful for? Pretty much nothing, IMHO, while having a shortcut to lazily obtain a single bound version of that method for that object can be useful in many ways, as example `obj.on('event', anotherObj::method)` where it's always possible at that point to `obj.removeListener('event', anotherObj::method)` in case its needed.

Having a shortcut that all it does is replace something already short to write like a `.bind` feels to me like a missed opportunity.

Moreover, with this improvement you won't need/care to have self-bound methods at all

```js
let obj = { method(){} };

// and whenever needed you use
obj::method;
```

Hope my POV is more clear now.

Regards









On Wed, Nov 11, 2015 at 4:01 PM, JD Isaacks <[hidden email]> wrote:
I think what you are suggesting already exists with `::obj.method` which evaluates to `obj.method.bind(obj)` 

However, this creates a new function each time so `::obj.method !== ::obj.method`, not sure how `::obj.method === ::obj.method` would work.

I sort of agree with you that using it that way would be preferred. However if the community wants bound methods attached to objects, there is currently no way to do that with an object literal.

You would have to do something like:

```
let obj = {};
obj.method = function(){}.bind(obj);
```

With my proposal you can.

```
let obj = { ::method(){} };
```




On Wed, Nov 11, 2015 at 10:20 AM, Andrea Giammarchi <[hidden email]> wrote:
Just my thoughts, I wouldn't put any self-bound thing in the class and rather improve that `::` proposal so that whenever you `obj::method` it creates a uniquely bound callback so that `obj::method === obj::method` and at that point whenever you need to export, pass, or use such method you just `obj::method` or `obj::method()` or `let method = obj::method` and bring the pattern whenever it's needed instead of being slightly different per each "place" (class rather than objects)

That would make it lazy, usable for events (in order to be able to also remove them) and easily transpilable for smoother migration.

Having `class A { ::method() {} }` feels like somebody is playing too much with the protoype or "accidentally" polluting the constructor

Regards


On Wed, Nov 11, 2015 at 2:50 PM, JD Isaacks <[hidden email]> wrote:
Andrea, Sort of. I am talking about adding an additional place where that operator `::` can be used -- with concise methods.

Currently they cannot be used in the way I described above but I think there are several reasons why it makes sense.

_______________________________________________
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: Re: Concise Method Binding

JD Isaacks
Pardon, I meant:

```
let bar = { foo(){} };

::bar.foo // bar.foo.bind(bar);
```
in my last example.


On Wed, Nov 11, 2015 at 11:23 AM, JD Isaacks <[hidden email]> wrote:
Yes your point of view is more clear now, I like this is a lot.

But I do not know how that would be transpiled or what the desugared version would look like. However, that would be awesome as you described.

A thing to note. You keep using `obj::method` which is different from `::object.method` the former is when method is not already attached to the object, the later is for then it is.

An example:

```
let foo = function(){};
let bar = {};

bar::foo // foo.bind(bar);
```

verses

```
let bar = { foo(){} };

::foo.bar // foo.bar.bind(foo);
```

I think both cases theoretically would be awesome to work as you described. Just fuzzy on how it would look underneath.

On Wed, Nov 11, 2015 at 11:14 AM, Andrea Giammarchi <[hidden email]> wrote:
Yeah, I've got that, my point is that whenever you need it you just `obj::method`

Your example indeed says that currently the proposal is that `obj::method` is similar to `obj.method.bind(obj)` which is indeed always different and indeed you want something that makes method always the same/unique bound one, which I believe is universally the preferred way.

What are two different bound of the same method useful for? Pretty much nothing, IMHO, while having a shortcut to lazily obtain a single bound version of that method for that object can be useful in many ways, as example `obj.on('event', anotherObj::method)` where it's always possible at that point to `obj.removeListener('event', anotherObj::method)` in case its needed.

Having a shortcut that all it does is replace something already short to write like a `.bind` feels to me like a missed opportunity.

Moreover, with this improvement you won't need/care to have self-bound methods at all

```js
let obj = { method(){} };

// and whenever needed you use
obj::method;
```

Hope my POV is more clear now.

Regards









On Wed, Nov 11, 2015 at 4:01 PM, JD Isaacks <[hidden email]> wrote:
I think what you are suggesting already exists with `::obj.method` which evaluates to `obj.method.bind(obj)` 

However, this creates a new function each time so `::obj.method !== ::obj.method`, not sure how `::obj.method === ::obj.method` would work.

I sort of agree with you that using it that way would be preferred. However if the community wants bound methods attached to objects, there is currently no way to do that with an object literal.

You would have to do something like:

```
let obj = {};
obj.method = function(){}.bind(obj);
```

With my proposal you can.

```
let obj = { ::method(){} };
```




On Wed, Nov 11, 2015 at 10:20 AM, Andrea Giammarchi <[hidden email]> wrote:
Just my thoughts, I wouldn't put any self-bound thing in the class and rather improve that `::` proposal so that whenever you `obj::method` it creates a uniquely bound callback so that `obj::method === obj::method` and at that point whenever you need to export, pass, or use such method you just `obj::method` or `obj::method()` or `let method = obj::method` and bring the pattern whenever it's needed instead of being slightly different per each "place" (class rather than objects)

That would make it lazy, usable for events (in order to be able to also remove them) and easily transpilable for smoother migration.

Having `class A { ::method() {} }` feels like somebody is playing too much with the protoype or "accidentally" polluting the constructor

Regards


On Wed, Nov 11, 2015 at 2:50 PM, JD Isaacks <[hidden email]> wrote:
Andrea, Sort of. I am talking about adding an additional place where that operator `::` can be used -- with concise methods.

Currently they cannot be used in the way I described above but I think there are several reasons why it makes sense.

_______________________________________________
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: Re: Concise Method Binding

Andrea Giammarchi-2
In reply to this post by JD Isaacks
The way it could work is similar to the following one:

```js

(function (wm){'use strict';

  // just to show the possible internal slot mechanism
  Object.prototype.boundTo = function (method) {
    // since I've used this for ages now in eddy.js, just replicating
    var fn = typeof method === 'function' ? method : this[method];
    var bound = wm.get(this);
    if (!bound) wm.set(this, bound = {fn:[], bound:[]});
    var i = bound.fn.indexOf(fn);
    if (i < 0) bound.bound[i = bound.fn.push(fn) - 1] = fn.bind(this);
    return bound.bound[i];
  };

}(new WeakMap));


// example
var obj = {method: function () { return this; }};

// now, whenever needed
obj.boundTo(obj.method);

// will create the slot and set it up with obj.method
// so that the following is true
obj.boundTo(obj.method) === obj.boundTo('method') &&
obj.boundTo('method')() === obj;

// if it's about another method
// the equivalent of this
::obj.anotherMethod

// whould be
obj.boundTo(anotherMethod);

```

The string fallback is not needed or relevant, it's just a semantic shortcut in my example to reach the method through the object without repeating the object name

Regards




On Wed, Nov 11, 2015 at 4:23 PM, JD Isaacks <[hidden email]> wrote:
Yes your point of view is more clear now, I like this is a lot.

But I do not know how that would be transpiled or what the desugared version would look like. However, that would be awesome as you described.

A thing to note. You keep using `obj::method` which is different from `::object.method` the former is when method is not already attached to the object, the later is for then it is.

An example:

```
let foo = function(){};
let bar = {};

bar::foo // foo.bind(bar);
```

verses

```
let bar = { foo(){} };

::foo.bar // foo.bar.bind(foo);
```

I think both cases theoretically would be awesome to work as you described. Just fuzzy on how it would look underneath.

On Wed, Nov 11, 2015 at 11:14 AM, Andrea Giammarchi <[hidden email]> wrote:
Yeah, I've got that, my point is that whenever you need it you just `obj::method`

Your example indeed says that currently the proposal is that `obj::method` is similar to `obj.method.bind(obj)` which is indeed always different and indeed you want something that makes method always the same/unique bound one, which I believe is universally the preferred way.

What are two different bound of the same method useful for? Pretty much nothing, IMHO, while having a shortcut to lazily obtain a single bound version of that method for that object can be useful in many ways, as example `obj.on('event', anotherObj::method)` where it's always possible at that point to `obj.removeListener('event', anotherObj::method)` in case its needed.

Having a shortcut that all it does is replace something already short to write like a `.bind` feels to me like a missed opportunity.

Moreover, with this improvement you won't need/care to have self-bound methods at all

```js
let obj = { method(){} };

// and whenever needed you use
obj::method;
```

Hope my POV is more clear now.

Regards









On Wed, Nov 11, 2015 at 4:01 PM, JD Isaacks <[hidden email]> wrote:
I think what you are suggesting already exists with `::obj.method` which evaluates to `obj.method.bind(obj)` 

However, this creates a new function each time so `::obj.method !== ::obj.method`, not sure how `::obj.method === ::obj.method` would work.

I sort of agree with you that using it that way would be preferred. However if the community wants bound methods attached to objects, there is currently no way to do that with an object literal.

You would have to do something like:

```
let obj = {};
obj.method = function(){}.bind(obj);
```

With my proposal you can.

```
let obj = { ::method(){} };
```




On Wed, Nov 11, 2015 at 10:20 AM, Andrea Giammarchi <[hidden email]> wrote:
Just my thoughts, I wouldn't put any self-bound thing in the class and rather improve that `::` proposal so that whenever you `obj::method` it creates a uniquely bound callback so that `obj::method === obj::method` and at that point whenever you need to export, pass, or use such method you just `obj::method` or `obj::method()` or `let method = obj::method` and bring the pattern whenever it's needed instead of being slightly different per each "place" (class rather than objects)

That would make it lazy, usable for events (in order to be able to also remove them) and easily transpilable for smoother migration.

Having `class A { ::method() {} }` feels like somebody is playing too much with the protoype or "accidentally" polluting the constructor

Regards


On Wed, Nov 11, 2015 at 2:50 PM, JD Isaacks <[hidden email]> wrote:
Andrea, Sort of. I am talking about adding an additional place where that operator `::` can be used -- with concise methods.

Currently they cannot be used in the way I described above but I think there are several reasons why it makes sense.

_______________________________________________
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: Concise Method Binding

Bergi
In reply to this post by Andrea Giammarchi-2
Andrea Giammarchi schrieb:
> Just my thoughts, I wouldn't put any self-bound thing in the class and
> rather improve that `::` proposal so that whenever you `obj::method` it
> creates a uniquely bound callback so that `obj::method === obj::method`

This was considered:
https://github.com/zenparsing/es-function-bind/issues/17 - it's quite
unexpected that an operator would return the same result every time, and
there are security considerations as well. Also it would be quite
complicated to spec - how and where did you store the memoisation. Feel
free to join the discussion!

Using the `::` operator in the class declaration itself makes sense to
me. It conveys "this method will always be bound" very effectively, and
you wouldn't even need special syntax to access it.
```js
class Xample {
   ::myListener(…) {…}
}
```
should desugar to
```js
class Xample {
   // a getter on the prototype
   get myListener() {
     // with per-instance memoisation
     return this.myListener = (…) => {
       // that returns a bound method
       …
     };
   }
}
```
It might be equivalently done via a custom decorator of course:
```js
class Xample {
   @autobind
   myListener(…) {…}
}
```

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

Re: Re: Concise Method Binding

JD Isaacks
In reply to this post by Andrea Giammarchi-2
I like this very much. I would prefer this to my recommendation. So how to we go about proposing it as a change to an existing proposal?

On Wed, Nov 11, 2015 at 11:45 AM, Andrea Giammarchi <[hidden email]> wrote:
The way it could work is similar to the following one:

```js

(function (wm){'use strict';

  // just to show the possible internal slot mechanism
  Object.prototype.boundTo = function (method) {
    // since I've used this for ages now in eddy.js, just replicating
    var fn = typeof method === 'function' ? method : this[method];
    var bound = wm.get(this);
    if (!bound) wm.set(this, bound = {fn:[], bound:[]});
    var i = bound.fn.indexOf(fn);
    if (i < 0) bound.bound[i = bound.fn.push(fn) - 1] = fn.bind(this);
    return bound.bound[i];
  };

}(new WeakMap));


// example
var obj = {method: function () { return this; }};

// now, whenever needed
obj.boundTo(obj.method);

// will create the slot and set it up with obj.method
// so that the following is true
obj.boundTo(obj.method) === obj.boundTo('method') &&
obj.boundTo('method')() === obj;

// if it's about another method
// the equivalent of this
::obj.anotherMethod

// whould be
obj.boundTo(anotherMethod);

```

The string fallback is not needed or relevant, it's just a semantic shortcut in my example to reach the method through the object without repeating the object name

Regards




On Wed, Nov 11, 2015 at 4:23 PM, JD Isaacks <[hidden email]> wrote:
Yes your point of view is more clear now, I like this is a lot.

But I do not know how that would be transpiled or what the desugared version would look like. However, that would be awesome as you described.

A thing to note. You keep using `obj::method` which is different from `::object.method` the former is when method is not already attached to the object, the later is for then it is.

An example:

```
let foo = function(){};
let bar = {};

bar::foo // foo.bind(bar);
```

verses

```
let bar = { foo(){} };

::foo.bar // foo.bar.bind(foo);
```

I think both cases theoretically would be awesome to work as you described. Just fuzzy on how it would look underneath.

On Wed, Nov 11, 2015 at 11:14 AM, Andrea Giammarchi <[hidden email]> wrote:
Yeah, I've got that, my point is that whenever you need it you just `obj::method`

Your example indeed says that currently the proposal is that `obj::method` is similar to `obj.method.bind(obj)` which is indeed always different and indeed you want something that makes method always the same/unique bound one, which I believe is universally the preferred way.

What are two different bound of the same method useful for? Pretty much nothing, IMHO, while having a shortcut to lazily obtain a single bound version of that method for that object can be useful in many ways, as example `obj.on('event', anotherObj::method)` where it's always possible at that point to `obj.removeListener('event', anotherObj::method)` in case its needed.

Having a shortcut that all it does is replace something already short to write like a `.bind` feels to me like a missed opportunity.

Moreover, with this improvement you won't need/care to have self-bound methods at all

```js
let obj = { method(){} };

// and whenever needed you use
obj::method;
```

Hope my POV is more clear now.

Regards









On Wed, Nov 11, 2015 at 4:01 PM, JD Isaacks <[hidden email]> wrote:
I think what you are suggesting already exists with `::obj.method` which evaluates to `obj.method.bind(obj)` 

However, this creates a new function each time so `::obj.method !== ::obj.method`, not sure how `::obj.method === ::obj.method` would work.

I sort of agree with you that using it that way would be preferred. However if the community wants bound methods attached to objects, there is currently no way to do that with an object literal.

You would have to do something like:

```
let obj = {};
obj.method = function(){}.bind(obj);
```

With my proposal you can.

```
let obj = { ::method(){} };
```




On Wed, Nov 11, 2015 at 10:20 AM, Andrea Giammarchi <[hidden email]> wrote:
Just my thoughts, I wouldn't put any self-bound thing in the class and rather improve that `::` proposal so that whenever you `obj::method` it creates a uniquely bound callback so that `obj::method === obj::method` and at that point whenever you need to export, pass, or use such method you just `obj::method` or `obj::method()` or `let method = obj::method` and bring the pattern whenever it's needed instead of being slightly different per each "place" (class rather than objects)

That would make it lazy, usable for events (in order to be able to also remove them) and easily transpilable for smoother migration.

Having `class A { ::method() {} }` feels like somebody is playing too much with the protoype or "accidentally" polluting the constructor

Regards


On Wed, Nov 11, 2015 at 2:50 PM, JD Isaacks <[hidden email]> wrote:
Andrea, Sort of. I am talking about adding an additional place where that operator `::` can be used -- with concise methods.

Currently they cannot be used in the way I described above but I think there are several reasons why it makes sense.

_______________________________________________
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: Re: Concise Method Binding

JD Isaacks
Ahh, good point Bergi. Thanks for brining that up.

On Wed, Nov 11, 2015 at 11:55 AM, JD Isaacks <[hidden email]> wrote:
I like this very much. I would prefer this to my recommendation. So how to we go about proposing it as a change to an existing proposal?

On Wed, Nov 11, 2015 at 11:45 AM, Andrea Giammarchi <[hidden email]> wrote:
The way it could work is similar to the following one:

```js

(function (wm){'use strict';

  // just to show the possible internal slot mechanism
  Object.prototype.boundTo = function (method) {
    // since I've used this for ages now in eddy.js, just replicating
    var fn = typeof method === 'function' ? method : this[method];
    var bound = wm.get(this);
    if (!bound) wm.set(this, bound = {fn:[], bound:[]});
    var i = bound.fn.indexOf(fn);
    if (i < 0) bound.bound[i = bound.fn.push(fn) - 1] = fn.bind(this);
    return bound.bound[i];
  };

}(new WeakMap));


// example
var obj = {method: function () { return this; }};

// now, whenever needed
obj.boundTo(obj.method);

// will create the slot and set it up with obj.method
// so that the following is true
obj.boundTo(obj.method) === obj.boundTo('method') &&
obj.boundTo('method')() === obj;

// if it's about another method
// the equivalent of this
::obj.anotherMethod

// whould be
obj.boundTo(anotherMethod);

```

The string fallback is not needed or relevant, it's just a semantic shortcut in my example to reach the method through the object without repeating the object name

Regards




On Wed, Nov 11, 2015 at 4:23 PM, JD Isaacks <[hidden email]> wrote:
Yes your point of view is more clear now, I like this is a lot.

But I do not know how that would be transpiled or what the desugared version would look like. However, that would be awesome as you described.

A thing to note. You keep using `obj::method` which is different from `::object.method` the former is when method is not already attached to the object, the later is for then it is.

An example:

```
let foo = function(){};
let bar = {};

bar::foo // foo.bind(bar);
```

verses

```
let bar = { foo(){} };

::foo.bar // foo.bar.bind(foo);
```

I think both cases theoretically would be awesome to work as you described. Just fuzzy on how it would look underneath.

On Wed, Nov 11, 2015 at 11:14 AM, Andrea Giammarchi <[hidden email]> wrote:
Yeah, I've got that, my point is that whenever you need it you just `obj::method`

Your example indeed says that currently the proposal is that `obj::method` is similar to `obj.method.bind(obj)` which is indeed always different and indeed you want something that makes method always the same/unique bound one, which I believe is universally the preferred way.

What are two different bound of the same method useful for? Pretty much nothing, IMHO, while having a shortcut to lazily obtain a single bound version of that method for that object can be useful in many ways, as example `obj.on('event', anotherObj::method)` where it's always possible at that point to `obj.removeListener('event', anotherObj::method)` in case its needed.

Having a shortcut that all it does is replace something already short to write like a `.bind` feels to me like a missed opportunity.

Moreover, with this improvement you won't need/care to have self-bound methods at all

```js
let obj = { method(){} };

// and whenever needed you use
obj::method;
```

Hope my POV is more clear now.

Regards









On Wed, Nov 11, 2015 at 4:01 PM, JD Isaacks <[hidden email]> wrote:
I think what you are suggesting already exists with `::obj.method` which evaluates to `obj.method.bind(obj)` 

However, this creates a new function each time so `::obj.method !== ::obj.method`, not sure how `::obj.method === ::obj.method` would work.

I sort of agree with you that using it that way would be preferred. However if the community wants bound methods attached to objects, there is currently no way to do that with an object literal.

You would have to do something like:

```
let obj = {};
obj.method = function(){}.bind(obj);
```

With my proposal you can.

```
let obj = { ::method(){} };
```




On Wed, Nov 11, 2015 at 10:20 AM, Andrea Giammarchi <[hidden email]> wrote:
Just my thoughts, I wouldn't put any self-bound thing in the class and rather improve that `::` proposal so that whenever you `obj::method` it creates a uniquely bound callback so that `obj::method === obj::method` and at that point whenever you need to export, pass, or use such method you just `obj::method` or `obj::method()` or `let method = obj::method` and bring the pattern whenever it's needed instead of being slightly different per each "place" (class rather than objects)

That would make it lazy, usable for events (in order to be able to also remove them) and easily transpilable for smoother migration.

Having `class A { ::method() {} }` feels like somebody is playing too much with the protoype or "accidentally" polluting the constructor

Regards


On Wed, Nov 11, 2015 at 2:50 PM, JD Isaacks <[hidden email]> wrote:
Andrea, Sort of. I am talking about adding an additional place where that operator `::` can be used -- with concise methods.

Currently they cannot be used in the way I described above but I think there are several reasons why it makes sense.

_______________________________________________
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: Re: Concise Method Binding

Gilbert B Garza
Forgive me if I'm missing the point, but isn't the entire purpose of using classes to make all instances share the same function in memory via `this` ? If you want methods to always be bound, why not use closures instead?

```js
function Person (name) {
  var person = this
  person.greet = function () {
    return person.name + " says hi!";
  };
}

var alice = new Person('Alice');
alice.greet() //=> "Alice says hi!";

var f = alice.greet;
f() //=> "Alice says hi!";
```

On Wed, Nov 11, 2015 at 10:59 AM, JD Isaacks <[hidden email]> wrote:
Ahh, good point Bergi. Thanks for brining that up.

On Wed, Nov 11, 2015 at 11:55 AM, JD Isaacks <[hidden email]> wrote:
I like this very much. I would prefer this to my recommendation. So how to we go about proposing it as a change to an existing proposal?

On Wed, Nov 11, 2015 at 11:45 AM, Andrea Giammarchi <[hidden email]> wrote:
The way it could work is similar to the following one:

```js

(function (wm){'use strict';

  // just to show the possible internal slot mechanism
  Object.prototype.boundTo = function (method) {
    // since I've used this for ages now in eddy.js, just replicating
    var fn = typeof method === 'function' ? method : this[method];
    var bound = wm.get(this);
    if (!bound) wm.set(this, bound = {fn:[], bound:[]});
    var i = bound.fn.indexOf(fn);
    if (i < 0) bound.bound[i = bound.fn.push(fn) - 1] = fn.bind(this);
    return bound.bound[i];
  };

}(new WeakMap));


// example
var obj = {method: function () { return this; }};

// now, whenever needed
obj.boundTo(obj.method);

// will create the slot and set it up with obj.method
// so that the following is true
obj.boundTo(obj.method) === obj.boundTo('method') &&
obj.boundTo('method')() === obj;

// if it's about another method
// the equivalent of this
::obj.anotherMethod

// whould be
obj.boundTo(anotherMethod);

```

The string fallback is not needed or relevant, it's just a semantic shortcut in my example to reach the method through the object without repeating the object name

Regards




On Wed, Nov 11, 2015 at 4:23 PM, JD Isaacks <[hidden email]> wrote:
Yes your point of view is more clear now, I like this is a lot.

But I do not know how that would be transpiled or what the desugared version would look like. However, that would be awesome as you described.

A thing to note. You keep using `obj::method` which is different from `::object.method` the former is when method is not already attached to the object, the later is for then it is.

An example:

```
let foo = function(){};
let bar = {};

bar::foo // foo.bind(bar);
```

verses

```
let bar = { foo(){} };

::foo.bar // foo.bar.bind(foo);
```

I think both cases theoretically would be awesome to work as you described. Just fuzzy on how it would look underneath.

On Wed, Nov 11, 2015 at 11:14 AM, Andrea Giammarchi <[hidden email]> wrote:
Yeah, I've got that, my point is that whenever you need it you just `obj::method`

Your example indeed says that currently the proposal is that `obj::method` is similar to `obj.method.bind(obj)` which is indeed always different and indeed you want something that makes method always the same/unique bound one, which I believe is universally the preferred way.

What are two different bound of the same method useful for? Pretty much nothing, IMHO, while having a shortcut to lazily obtain a single bound version of that method for that object can be useful in many ways, as example `obj.on('event', anotherObj::method)` where it's always possible at that point to `obj.removeListener('event', anotherObj::method)` in case its needed.

Having a shortcut that all it does is replace something already short to write like a `.bind` feels to me like a missed opportunity.

Moreover, with this improvement you won't need/care to have self-bound methods at all

```js
let obj = { method(){} };

// and whenever needed you use
obj::method;
```

Hope my POV is more clear now.

Regards









On Wed, Nov 11, 2015 at 4:01 PM, JD Isaacks <[hidden email]> wrote:
I think what you are suggesting already exists with `::obj.method` which evaluates to `obj.method.bind(obj)` 

However, this creates a new function each time so `::obj.method !== ::obj.method`, not sure how `::obj.method === ::obj.method` would work.

I sort of agree with you that using it that way would be preferred. However if the community wants bound methods attached to objects, there is currently no way to do that with an object literal.

You would have to do something like:

```
let obj = {};
obj.method = function(){}.bind(obj);
```

With my proposal you can.

```
let obj = { ::method(){} };
```




On Wed, Nov 11, 2015 at 10:20 AM, Andrea Giammarchi <[hidden email]> wrote:
Just my thoughts, I wouldn't put any self-bound thing in the class and rather improve that `::` proposal so that whenever you `obj::method` it creates a uniquely bound callback so that `obj::method === obj::method` and at that point whenever you need to export, pass, or use such method you just `obj::method` or `obj::method()` or `let method = obj::method` and bring the pattern whenever it's needed instead of being slightly different per each "place" (class rather than objects)

That would make it lazy, usable for events (in order to be able to also remove them) and easily transpilable for smoother migration.

Having `class A { ::method() {} }` feels like somebody is playing too much with the protoype or "accidentally" polluting the constructor

Regards


On Wed, Nov 11, 2015 at 2:50 PM, JD Isaacks <[hidden email]> wrote:
Andrea, Sort of. I am talking about adding an additional place where that operator `::` can be used -- with concise methods.

Currently they cannot be used in the way I described above but I think there are several reasons why it makes sense.

_______________________________________________
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



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