- Partial application is fundamental to functional-style programming
- It is the binding of arguments to parameters before a function is invoked
- This technique is often used by ECMAScript developers who are:
- seeking to avoid the use of
new
and/orthis
- deliberately trying to avoid function genericism
- trying to improve consistency of style
- seeking to avoid the use of
- Partial application is currently supported by
Function.prototype.bind
, but the syntax is verbose, and the target of the bound function comes first, diluting the semantic - Writing a custom function to provide partial application is straightforward (indeed there are many open source libraries providing this such as
_.partial
), however developers taking this approach are constrained in their ability to achieve syntactic tenseness lest they surprise other developers - A terse, native syntax for partial application that does not affect the target of a function will improve consistency, clarity of intent and legibility
Introduce two partial-application operators :>:
(partially apply left-to-right) and :<:
(partially apply right-to-left). These operators create a bound function such that the arguments to be supplied to the function on the left-hand side of the operator, when it is eventually invoked, are bound to those values supplied on the right-hand side of the operator.
import _ from 'lodash';
const o = {
foo: _.partial(foo, arg1),
bar: bar.bind(null, arg1, arg2)
};
const o = {
foo:>:arg1,
bar:>:[arg1, arg2]
};
Promise.resolve()
.then(() => foo(arg1));
Promise.resolve()
.then(foo:>:arg1);
const arg1 = 'this is arg1';
function foo(arg1) { console.log(arg1); }
// Current syntax 1
o = { foo: foo.bind(null, arg1) };
// Current syntax 2
let o = { foo: _.partial(foo, arg1) };
// Current syntax 3
let o = { foo: (...args) => foo(arg1, ...args) };
// Proposed syntax
o = { foo:>:arg1 };
o.foo(); // 'this is arg1' printed to console
Use as part of an assignment expression:
const bound = foo:>:context;
As part of a return statement with the spread operator:
function curry(foo, ...args) { return foo:>:[...args]; };
Partial application with multiple arguments. The right-hand side value may be either a single value or an array of arguments:
var bound = foo:>:['a','b'];
If the single value needs to be an array we need to disambiguate:
var bound = foo:>:(['a','b']);
Partial application from the right:
const foo = (a, b) => console.log(a, b);
var bound = foo:<:['this is b'];
bound('this is a'); // 'this is a, this is b' printed to console
- I am an unsophisticate with respect to syntax ambiguity avoidance
- The proposed syntax is merely a first guess and I am confident there will be better ideas
- I originally chose the syntax
::
for the operator, but there is another stage 0 proposal that intends to use that syntax for a different purpose. Also the revised syntax permits identification of the binding direction (from left/from right)
Some comments to help improve the proposal:
Function.prototype.partial
-like proposal?_.partial(foo, [arg1, arg2])
with this proposal?obj.func:>:arg1
be likeobj.func.bind(null, arg1)
orobj.func.bind(obj, arg1)
?arg1
evaluated in the examples?About my last point, the two following cases have different behavior, which behavior will this new operator follow?