Partial Application Syntax - TC39 Proposals

この記事は2019年10月9日に書いたものであり、[#tc39_study TC39 Proposals LT 大会](https://web-study.connpass.com/event/147538/)で使用したものです。

---
## 状況
- Stage : 1  
- URL : https://github.com/tc39/proposal-partial-application
- Champion : [Ron Buckton](https://github.com/rbuckton)
  - MSの人でTypeScript Compiler周りの人

---

### 提案内容
bindやarrow functionを使わなくても、` ? `を使用して引数を固定しないようにできる。

---

Partial Application Syntaxだとこれが

```javascript

function add(x, y) { return x + y; }

// Function#bind
const addOne = add.bind(null, 1);
addOne(2); // 3

// arrow functions
const addTen = x => add(x, 10);
addTen(2); // 12

// arrow functions and pipeline
const newScore = player.score
  |> _ => add(7, _)
  |> _ => clamp(0, 100, _);
```

---

こうなる

```javascript

const addOne = add(1, ?); 
addOne(2); // 3

const addTen = add(?, 10); 
addTen(2); // 12

// with pipeline
let newScore = player.score
  |> add(7, ?)
  |> clamp(0, 100, ?); 

// partial template strings
const Diagnostics = {
  unexpected_token: `Unexpected token: ${?}`,
  name_not_found: `'${?}' not found.`
};
Diagnostics.name_not_found("foo"); // "'foo' not found."
```
---

- bindだと先行引数のみしか引数を変更できない、thisを明示的に示す必要がある
- arrow functionはpipelineと組み合わせると複雑になる

---

## Examples

```javascript

// ○
f(x, ?)           // partial application from left
f(?, x)           // partial application from right
f(?, x, ?)        // partial application for any arg
o.f(x, ?)         // partial application from left
o.f(?, x)         // partial application from right
o.f(?, x, ?)      // partial application for any arg
super.f(?)        // partial application allowed for call on |SuperProperty|

// ×
f(x + ?)          // `?` not in top-level Arguments of call
x + ?             // `?` not in top-level Arguments of call
?.f()             // `?` not in top-level Arguments of call
new f(?)          // `?` not supported in `new`
super(?)          // `?` not supported in |SuperCall|
```
---
```javascript
const log = console.log({ toString() { return `[${new Date()}]` } }, ?);
log("test"); // [2018-07-17T23:25:36.984Z] test
```

```javascript

button.addEventListener("click", this.onClick(?));
```

---

```javascript
class Collator {
  constructor() {
    this.compare = this.compare(?, ?);
  }
  compare(a, b) { ... }
}
```

```javascript

// doWork expects a callback of `(err, value) => void`
function doWork(callback) { ... }
function onWorkCompleted(err, value, state) { ... }
doWork(onWorkCompleted(?, ?, { key: "value" }));
```

---

```javascript
const slice = Array.prototype.slice.call(?, ?, ?);
slice({ 0: "a", 1: "b", length: 2 }, 1, 2); // ["b"]
```
---

```javascript
// AST transformation
const newNode = createFunctionExpression(oldNode.name, visitNodes(oldNode.parameters), visitNode(oldNode.body))
  |> setOriginalNode(?, oldNode)
  |> setTextRange(?, oldNode.pos, oldNode.end)
  |> setEmitFlags(?, EmitFlags.NoComments);
```
---

## Support for rest/spread (...)
これ便利そう

```javascript

function f(a, b, c, d) { console.log(`a: ${a}, b: ${b}, c: ${c}, d: ${d}`); }
const g = f(?, 1, ...);
g(2);       // a: 2, b: 1, c: undefined, d: undefined
g(2, 3);    // a: 2, b: 1, c: 3, d: undefined
g(2, 3, 4); // a: 2, b: 1, c: 3, d: 4
```