この記事は2019年10月9日に書いたものであり、#tc39_study TC39 Proposals LT 大会で使用したものです。
状況
- Stage : 1
- URL : https://github.com/tc39/proposal-partial-application
- Champion : Ron Buckton
- MSの人でTypeScript Compiler周りの人
提案内容
bindやarrow functionを使わなくても、?
を使用して引数を固定しないようにできる。
Partial Application Syntaxだとこれが
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, _);
こうなる
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
// ○
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|
const log = console.log({ toString() { return `[${new Date()}]` } }, ?);
log("test"); // [2018-07-17T23:25:36.984Z] test
button.addEventListener("click", this.onClick(?));
class Collator {
constructor() {
this.compare = this.compare(?, ?);
}
compare(a, b) { ... }
}
// doWork expects a callback of `(err, value) => void`
function doWork(callback) { ... }
function onWorkCompleted(err, value, state) { ... }
doWork(onWorkCompleted(?, ?, { key: "value" }));
const slice = Array.prototype.slice.call(?, ?, ?);
slice({ 0: "a", 1: "b", length: 2 }, 1, 2); // ["b"]
// 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 (...)
これ便利そう
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