Given that these function declarations exist within scope:
function compose() {
var funcs = arguments;
return function() {
var args, i;
args = arguments;
for (i = funcs.length - 1; i >= 0; i--) {
args = [funcs[i].apply(null, args)];
}
return args[0];
};
}
function id(x) {
return x;
}
function partial(targetfn) {
var arity = targetfn.length;
return function fn() {
if (arguments.length < arity) {
return Function.prototype.bind.apply(fn, [null].concat(
Array.prototype.slice.call(arguments)
));
} else {
return targetfn.apply(null, arguments);
}
}
}
Having this callback function as an example:
function cb(x, y) {
console.log(x);
console.log(y);
}
Is it possible using FP techniques (such as argument binding, composition and partial application) to apply the callback function to 2 arrays of arbitrary length? E.g.: ["foo", "bar", "baz", "quux"] and [12, 42]? The expected output in this case would be:
foo
12
foo
42
bar
12
bar
42
baz
12
...and so on
Since Array.prototype.forEach and Array.prototype.map pass 3 arguments to the callback function, it's at least possible to iterate over a single array using function composition as follows:
["foo", "bar", "baz", "quux"].forEach(compose(cb, id))
It's also possible to map an array into partially applied functions like so:
[12, 42].map(compose(partial(cb), id))
I've been looking into using Function.prototype.apply, Function.prototype.bind and Function.prototype.call, combining them with Array.prototype.forEach and Array.prototype.map, so far without success. I'm trying hard not to introduce more function declarations / expressions.
Update
Thanks to Mulan, the problem can be solved by splitting it into the part that computes the cartesian product of lists and applying the resulting list to a given function.
function product() {
var args = [].slice.call(arguments);
return args.reduce(function(prev, cur) {
var ret = [];
prev.forEach(function(x) {
cur.forEach(function(y) {
ret.push(x.concat(y));
});
});
return ret;
}, args.shift().map(function(val) {
return [val];
}));
}
product(
["foo", "bar", "baz", "quux"],
[12, 42]
).forEach(Function.prototype.apply.bind(cb, null));