Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

--> function binder shorthand? #1071

Open
determin1st opened this issue Oct 4, 2018 · 9 comments
Open

--> function binder shorthand? #1071

determin1st opened this issue Oct 4, 2018 · 9 comments
Labels

Comments

@determin1st
Copy link

determin1st commented Oct 4, 2018

for example, i have this code:

api =
  method: (me) -> !->
    me.flag = true

it compiles to:

api = {
  method: function(me){
    return function(){
      me.flag = true;
    };
  }
};

later, i iterate a list of those methods and bind them with this code:

for name in apiList
  @[name] = api[name] @

i could do:

for name in apiList
  @[name] = api[name].bind @

but with multiple objects, function.prototype.bind works slow.
what you think about this syntax:

api =
  method: (me) !-->
    me.flag = true

..or, if it does return something, it could be --> without !. i could use let syntax, but it creates binder functions each time. how to approach this?

@determin1st
Copy link
Author

determin1st commented Oct 4, 2018

hmm.. not good. sorry. ->-> is okay.. was in hurry.... wanted to use @ inside those methods..

@rhendric
Copy link
Collaborator

rhendric commented Oct 5, 2018

I'm sorry, I don't quite understand what you're proposing... perhaps you figured out that --> already means something? What should be shorthand for what here?

@determin1st
Copy link
Author

determin1st commented Oct 5, 2018

well, i thought about this syntax

method = (param1, param2) !-->
  @property = true

to this syntax

method = function(this$) {
  return function(param1, param2) {
    this$.property = true;
  };
};

so, it will act like bind with only first parameter thisArg specified (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)

--> - is free, it does not generate any syntax, only simple function.

It looks very implicit.. ye. but if you know how you defined it shouldn't be the problem. shorthand is for both function and first parameter that will become @ inside the body.

@rhendric
Copy link
Collaborator

rhendric commented Oct 5, 2018

method = (param1, param2) !-->
  @property = true

currently produces a curried function, so that exact syntax is out.

However, there's precedent for ‘assigning to this’ with the let keyword, so perhaps instead of yet another arrow variant, could we compromise on the below?

method = (this) -> (param1, param2) !~>
  @property = true

(The ~ would be necessary to keep the inner function using the same this as the outer one.)

It's more verbose than your proposal, but also more explicit and made of more reusable parts.

@determin1st
Copy link
Author

determin1st commented Oct 5, 2018

oh, i didn't noticed that with parameters it will be curried function...

well, i like (this) -> (param) ~> more than (me) -> (param) ->, ye, it will be more useful,
but it doesnt work for now, says compile error..

in case, when there is no parameters in the inner function it will be:

method = (this) -> !~>
  @property = true

which doesn't look great, right?
what about using more compact syntax with this or @ as the first parameter to make binder:

method1 = (this) !~>
  @property = true

method2 = (this, param1, param2) !~>
  @property = true

hmm.. docs are saying that ~> creates a bound function, so,
some crazy idea came now, it probably can be used to create variable binder like:

method1 = (this, boundParam1, param2, param3) !~~>
  @property = true

method2 = (this, boundParam1, boundParam2, param3) !~~~>
  @property = true

or better

method1 = (this, boundParam1, [param2, param3]) !~>
  @property = true

method2 = (this, boundParam1, boundParam2, [param3]) !~>
  @property = true

but i compromise to your variant, anyway

@rhendric
Copy link
Collaborator

rhendric commented Oct 9, 2018

Repeating the ‘shaft’ of a function arrow (-> to -->, ~> to ~~>, etc.) is the cue to make the function curried, so we can't use that as a clue for how many parameters should be bound.

On principle, I'm opposed to two things that these last few suggestions would require:

  • creating the equivalent of more than one function with a single (non-curried) arrow symbol
  • letting the presence of this in the parameter list significantly change how the rest of the parameter list is interpreted

I'll take this in parameter lists as a low priority feature for now. There are possibly some issues that I need to think about further—consider the following:

f = (this, a = @a) -> a

should probably compile to

var f;
f = function(this$, a){
  a == null && (a = this$.a);
  return a;
};

and

f = (a, {obj: this} = a) -> @foo

should compile to

var f;
f = function(a, arg$){
  var this$;
  this$ = (arg$ != null ? arg$ : a).obj;
  return this$.foo;
};

but then for consistency, I think

f = (a = @a, {obj: this} = a) -> @foo

has to compile to

var f;
f = function(a, arg$){
  var this$;
  a == null && (a = this.a);
  this$ = (arg$ != null ? arg$ : a).obj;
  return this$.foo;
};

so the effect of this-parameters can reach forward but not backward through the parameter list. I think that's probably fine? Anyone else think that this is possibly fishy, or see anything else wrong with the proposal?

@determin1st
Copy link
Author

determin1st commented Oct 9, 2018

Okay, i understand your first example, but the rest look complicated to me, why not reduce the syntax trigger to only the first this parameter specified, for now, and in other cases, drop syntax errors?
That will be easier, i think, and maybe later you will come up with other cases.
Also, you skipped binder variant, how do you see binder?

i mean something like this:

method = (this, param1, [param2, param3]) !~>
  @property = true

to

var method = function(this$, param1) {
  return function(param2, param3) {
    this$.property = true;
  };
};

..using this as first parameter perfectly fits the MDN docs (about .bind)

@rhendric
Copy link
Collaborator

rhendric commented Oct 9, 2018

Again, I don't want to create more than one function with a single arrow symbol. So to create that JavaScript code, which contains a function that returns a function, you'd write

method = (this, param1) -> (param2, param3) !~>
  @property = true

Sorry if I confused you with all those other examples; they weren't meant to apply to your use case. What I'm trying to do is show the implications of letting this be bound in a function parameter, and how that would interact with other advanced features of function parameters in LiveScript. It's important for us to work through potentially complicated interactions before we put new features in, to make sure that we don't box ourselves into any corners that it would then be hard to get out of without breaking backwards compatibility.

@determin1st
Copy link
Author

Okay, now i got it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants