1 of 8

Partial Application Update

Ron Buckton, Microsoft Corporation

2 of 8

Motivations

  • Additional capabilities for functional programming style.
  • Syntactic alternative for ‘Function.prototype.bind’, with additional capabilities:
    • Can “fix” arguments in any position (‘bind’ can only fix leading arguments).
    • Can “fix” Reference to preserve ‘this’ receiver (‘bind’ requires explicit argument for ‘this’).
    • Explicit non-”fixed” arguments (‘bind’ always passes on extra arguments).
  • Improved expressiveness when paired with F#-style pipeline proposal:
    • Significantly reduce need for Arrow functions in pipeline steps.
    • Avoids stack depth and closure ambiguity caused by using arrow functions in pipelines.
  • (new) Simplify reusable template expressions with placeholder arguments.

3 of 8

Proposal

  • Use ‘?’ token as argument placeholder in ArgumentList or TemplateMiddle (but nowhere else).
    • Each use of ‘?’ indicates a new argument in the resulting function.
    • Disallowed with `new`.
  • Reference and other arguments are evaluated (eagerly) and become “fixed”.
  • Result is a “partially applied function” with arguments for each placeholder.
  • Also under consideration:
    • ‘…’ token as rest/spread placeholder (only allowed once).
    • ‘?0’, ‘?1’, etc. as positional argument placeholder (allowed repeatedly, “dummy” arguments added for gaps in argument list).
    • Allow use with `new`.

4 of 8

Examples

// “fix” arguments in any position�[1, 2, 3].map(add(?, 1)); // [2, 3, 4]��// preserves `this`�button.onclick = this.onClick(?);��// F#-style pipelines�books � |> filter(?, x => x.category === "programming")� |> map(?, x => x.author)��// templates�const hello = `Hello ${?}!`;�hello("Alice"); // Hello Alice!

5 of 8

What Has Changed

  • PR: https://github.com/tc39/proposal-partial-application/pull/22
  • Specified eager evaluation for all “fixed” arguments.
  • Clarifications in explainer:
    • `f(g(?))` is roughly equivalent to `f(x => g(x))` (use an arrow if you want `x => f(g(x))`).
    • `?` is not an expression.
    • `? + x` is disallowed (use an arrow instead).
    • `?.f()` is disallowed (use an arrow instead).
    • `f({ x: ? })` is disallowed (use an arrow instead).
  • Dropped initial support for `...` token (may reintroduce).
  • Added support for `?` in a TemplateExpression/TaggedTemplateExpression.
  • Disallowed use with `new` for now, may reopen in the future.

6 of 8

Open Issue - “Garden Path” problem

  • Issue: https://github.com/tc39/proposal-partial-application/issues/13
  • The “Garden Path” problem is not a hard-and-fast requirement for the specification, as we already have other syntax with this problem:
    • Arrow functions: `(a, b)` could be parenthesized comma or start of arrow depending on whether next token is `=>`.
    • Destructuring: `[a, b]` could be array or assignment pattern depending on whether next token is `=`.
  • We believe there is sufficient motivation for this feature to make syntax worthwhile in spite of “garden path”.

7 of 8

Open Issue - ‘?’ token

  • Issue: https://github.com/tc39/proposal-partial-application/issues/21
  • Concerns use of `?` token in light of optional chaining/coalesce proposals.
  • After much research, `?` is still the best token for this proposal:
    • Least syntactic complexity with grammar compared to other tokens.
    • Best semantic meaning compared to other tokens.
  • In practice, combined use of partial application and optional chaining is not overly complicated or hard to read:
    • fn(?, a?.b ?? c)
  • In the worst case, it is no worse than any other combinations of similar tokens in legal ECMAScript:
    • a+++b+c-d---e
    • [a[b[0]][1],[c[[1][0]]]]

8 of 8

Summary

  • Champion:
    • Ron Buckton
  • Explainer:
  • Status:
    • Stage 1