JavaScript partially applied function - How to bind only the 2nd parameter?
Of course you can do it. Here's an ES6 solution using the spread operator (...
), since it's a bit more compact.
// Bind arguments starting after however many are passed in.
function bind_trailing_args(fn, ...bound_args) {
return function(...args) {
return fn(...args, ...bound_args);
};
}
If you'd prefer to specify the position at which binding starts:
// Bind arguments starting with argument number "n".
function bind_args_from_n(fn, n, ...bound_args) {
return function(...args) {
return fn(...args.slice(0, n-1), ...bound_args);
};
}
IN ES5, you have to muck around with constructing argument lists.
// ES5 version: construct arguments lists yourself
function bind_trailing_args(fn) {
var bound_args = [].slice.call(arguments, 1);
return function() {
var args = [].concat.call(arguments, bound_args);
return fn.apply(this, args);
};
}
Unlike the first two examples, this one handles this
properly.
In the context of your example:
var addThree = bind_trailing_args(add, 3);
addThree(1) // calls add(1, 3)
You could also consider using one of the functional programming libraries available for JS, such as http://osteele.com/sources/javascript/functional/. The thing you want is called rcurry
there.
You can use lodash's _.bind
to achieve this:
var add = function(a, b) {
document.write(a + b);
};
// Bind to first parameter (Nothing special here)
var bound = _.bind(add, null, 3);
bound(4);
// → 7
// Bind to second parameter by skipping the first one with "_"
var bound = _.bind(add, null, _, 4);
bound(3);
// → 7
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.min.js"></script>
I am usually against libraries and prefer coding my own utility functions, but an exception can easily be made for lodash. I would highly suggest you check its documentation whenever you have a "This must be in the language somewhere!" moment. It fills in a lot of blanks in JavaScript.
Well. I'll just throw this out there.
var add = function(a,b) {
return a + b;
};
var addThree = function(a) {
return add(a,3);
};
add(1,2);
addThree(4);
Maybe it will be ok for some.