tc39 / proposal-bind-operator

This-Binding Syntax for ECMAScript
1.75k stars 30 forks source link

Partially applied parameters #15

Closed maxnordlund closed 8 years ago

maxnordlund commented 9 years ago

The proposed syntax doesn't cover the other use of bind, namely partially application of function parameters. I've been thinking how this could be solved, and come up with this:

Either the current call syntax will be repurposed as extra arguments for bind:

foo::bar(a, b, ...rest) // bar.bind(foo, a, b, ...rest)

However this makes the suggested common use awkward,

(document.querySelectorAll("p")
  ::map)((el) => el.id) // Wrap whole expression in parenthesis, then call
  ::filter((id) => /^[A-Z]/.test(id))() // Bind all parameters, then call

The other way I found is to use parenthesis on the left hand side to indicate more parameters, which menas that the common case of only supplying a this value would be seen as having implicit parenthesis.

(foo, a, b, ...rest)::bar // bar.bind(foo, a, b, ...rest)

This case would be more backwards compatible then the above, but might be more confusing to read. It does however clearly distinguish between bound and call parameters.

I came upon this when writing a curry decorator and ended up using Function.prototype.bind.bind(bar, foo)(...arguments) which babel compiles to Function.prototype.bind.bind(bar, foo).apply(undefined, arguments).

What do you think? Anything I missed?

Edit Change currying -> partial application per https://github.com/zenparsing/es-function-bind/issues/15#issuecomment-110892162

msegado commented 8 years ago

@maxnordlund / @nathggns / others, anyone interested in throwing together a strawman for partial application or finding somewhere else where we can discuss? Partial application was recently identified as a separate issue here too: mindeavor/es-pipeline-operator#20.

That said, the es-pipeline-operator folks make a very good point: arrow functions already allow a fairly concise partial application syntax. For example, my proposed add2 = add(2, ...) from above could be written in plain old ES2015 as

add2 = (...x) => add(2, ...x);

It's true that this has slightly different behavior (it'll also fix this, which means this won't be set to the element if it's used as an event handler), but it's unclear if that's problematic enough to warrant new syntax.

maxnordlund commented 8 years ago

Not quite, arrow functions implicitly bind the current lexical this, which at least I didn't think your add(2, ...) did.

msegado commented 8 years ago

@maxnordlund Yeah, I think I realized that at the end of my post above but never went back and changed the beginning >.<

What I meant to convey was the following: