function variadic(fun, val0f, val1f) {return function() {var len = arguments.length;if (len == 0) {return val0f();} else if (len == 1) {if (val1f != undefined) {return val1f(arguments[0]);}else {return arguments[0];}} else {var tmp = fun(arguments[0], arguments[1]);for (index = 2; index < len; index++) {tmp = fun(tmp, arguments[index]);}return tmp;}};}
The 'variadic' function takes three parameters:
- the binary function;
- a function that returns the value for the variadic version when called with zero arguments
- a function that returns the value for the variadic version when called on a single. If not specified, the first argument to the variadic function is returned as is when called on a single argument.
For example, the summation operator is defined as
var sum = variadic(function(x,y) {return x+y;},function() { return 0;},function(x) { return x;});
while the equivalent of Scheme's / function is defined as
var div = variadic(function(x,y) {return x/y; },function() { throw "not enough arguments to div"; },function(x) { return 1/x;});
div.apply(this, [1,2,3,4,5])
to get 0.008333333333333333.
4 comments:
Math.max() isn't a binary function.
Math.max(1,2,3,4,5) // => 5
@Jon-Carlos You are absolutely right. I was totaly mistaken on that one. Thanks!
Since it's basically the reduce (or left fold) operation, you can make a version for simple functions using Array.prototype.reduce found in Javascript 1.8 or ECMA 5th edition.
var variadicify = function () {
var args = arguments;
return function () {
return Array.prototype.reduce.apply(arguments, args);
}
};
var findMax = variadicify(function (x,y) { return Math.max(x,y) }, Number.NEGATIVE_INFINITY);
findMax(1,2,3,4); // 4
var sum = variadicify(function (x, y) { return x + y }, 0);
sum() // 0
sum(1) // 1
sum(1,2,3,4) // 10
@Christian Nice! I always forget that ECMAScript 5th edition includes the reduce function...
Post a Comment