I have a function in search of a name.
I've been building a new functional programming library in Javascript, and I recently added a new function that looks useful to me. I named it useWith
but I'm wondering if it's a function already known to functional programmers under a different name.
The function is related to compose
in that it returns a new function that combines several existing ones, but in a slightly different manner than compose
. The first parameter it receives is singled out; the remainder are treated uniformly. When the returned function is called, the arguments are passed respectively to each of these remaining functions, and the results, along with any unpaired arguments are sent to that first function, whose result is then returned. So if this is called with only two functions, and if the resulting function is passed a single argument, this is exactly equivalent to compose. But it has some additional features for multiple arguments.
The reason I wanted this function was that I was implementing something like the project
function
Michal Fogus presented in Functional Javascript, an equivalent of Codd's project
for an array of similar Javascript objects, and similar to SQL's select
verb. It is quite easy to write like this:
var project = curry(function(keys, table) {
return map(pick(keys), table);
});
// Used like this:
var kids = [{name: 'Bob', age: 3, eyes: 'blue', hair: 'brown'},
{name: 'Sue', age: 5, eyes: 'hazel', hair: 'blonde'}];
project(['name', 'eyes'], kids);
//=> [{name: 'Bob', eyes: 'blue'}, {name: 'Sue', eyes: 'hazel'}]
But I really wanted to implement it in a points-free style. But of course this wouldn't work:
var project = compose(map, pick); // NO!
...because there is no facility to pass through the second parameter, table
inside compose
.
That's where this new function comes in:
var project = useWith(map, pick);
I made it more generic than this case, though. The original approach was called using
with the parameters reversed, so that it read as a command: "Using pick, map". But that made it hard to extend to multiple parameters. I'd have to make the first one an array, or allow it to be either an array or a single function, and I didn't really want to go there. This seemed a much better solution.
I feel as though I can't be the first person with the need for a function like this. Is this a common pattern in FP languages? Is there a common name for this function? If not, are there suggestions for a better name than useWith
?
If you're curious, here's the implementation of useWith
, using a pretty obvious slice
, and a fairly standard curry
:
var useWith = curry(function(fn /*, tranformers */) {
var tranformers = slice(arguments, 1);
return function() {
var args = [], idx = -1;
while (++idx < tranformers.length) {
args.push(tranformers[idx](arguments[idx]))
}
return fn.apply(this, args.concat(slice(arguments, tranformers.length)));
};
});