Currying enhanced

evolution of one function

Alex Khomenko
2 min readApr 29, 2014

For last years I’m trying to write my JavaScript in functional way. The main purpose of this is function which can be used in map, reduce, forEach fns.

Evolution

At first I tried to use just different function for slightly different cases:

function setProp(el, prop, val) { return el[prop] = val; }function setParent(el, val) { 
return setProp(el, 'parent', val);
}
var parent = { surname: 'Alpha' };
var kids = [{ name: 'A' }, { name: 'B' }];
kids.forEach(function (kid) { setParent(kid, parent); })

All this is pretty clear but I don’t want to create function every time I need to set<Something>. So setParent becomes:

function setParent(val) {
return function (el) {
setProp(el, 'parent', val);
};
}
kids.forEach(setParent(parent));

Invoking setParent(parent) I create function which has in closure `parent` and pass it (only one function, not bunch of them in case of anonymous fns) to iterator.

But sometimes functions became more and more sophisticated and I can not specify all parameters at once. Also I’m not willing to create additional function setParent, I’m good enough with setProp. So I started playing with bind

var setParent = setProp.bind(null, undefined, 'parent', parent);

I assumed that if I pass undefined or null I will pass them later in newly create function. But bind doesn’t work like this. setParent here is the same as setProp(undefined, ‘parent’, parent). So I came up with curry fns which is slightly modified from John Resig curry.

var curry = (function () {

function mergeArgs(arr1, arr2) {
var next = 0, result;
result = arr1.map(function (a1) {
return a1 === curry.SHD ? arr2[next++] : a1;
});

return result.concat(arr2.slice(next));
}

function curry(fn) {
var defArgs = Array.prototype.slice.call(arguments, 1);
return function () {
var args = Array.prototype.slice.call(arguments);
return fn.apply(this, mergeArgs(defArgs, args));
};
}

// shadow - placeholder in curry function
curry.SHD = {};

return curry;
}());

For placeholder in curry I use curry.SHD. At last I can do this ☺

kids.forEach(curry(setProp, curry.SHD, 'parent', parent));

Conclusion

Currying is very powerful technic which allow you utilize higher order function in the very efficient way.

Gist: https://gist.github.com/okhomenko/11404800

--

--