Skip to content

Instantly share code, notes, and snippets.

@silentmatt
Created June 19, 2009 18:43
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save silentmatt/132782 to your computer and use it in GitHub Desktop.
Save silentmatt/132782 to your computer and use it in GitHub Desktop.
Functions for dealing with function parameters
/*
Get an array of parameter names for a function.
Example:
js> function f(a, b, c) { return a + b * c; }
js> JSON.stringify(Function.parameters(f));
["a","b","c"]
*/
Function.parameters = function(f) {
var m = /function[^\(]*\(([^\)]*)\)/.exec(f.toString());
if (!m) {
throw new TypeError("Invalid function in parameters");
}
var params = m[1].split(',');
for (var i = 0; i < params.length; i++) {
// trim any spaces
params[i] = params[i].replace(/^\s*|\s*$/g, '');
}
return params;
};
/*
Create a new function that accepts its parameters in an object instead of
its positional parameters. An optional array of names can be provided
instead of using the parameters defined in the function (to rename
parameters, or since some functions might use parameters that aren't named).
Examples:
js> function f(a, b, c) { return a + b * c; }
js> f(1, 2, 3);
7
js> var f1 = Function.withNamedParameters(f);
js> f1({ a:1, b:2, c:3 });
7
js> // Call with an array (like f.apply)
js> var f2 = Function.withNamedParameters(f, [0, 1, 2]);
js> f2([1, 2, 3]);
7
*/
Function.withNamedParameters = function(f, params) {
// XXX: should this force f to be a function, or should anything that passes
// the parameters RegExp with an apply function work?
params = params || Function.parameters(f);
return function(args) {
var argsArray = new Array(params.length);
for (var i = 0; i < params.length; i++) {
argsArray[i] = args[params[i]];
}
return f.apply(this, argsArray);
};
};
/*
Create a new function that accepts its positional parameters as objects
mapping parameter names to values. Each parameter array maps ascending
arguments to properties in an object. With a single parameter array, this is
the opposite of Function.withNamedParameters.
Examples:
js> function f(p1, p2) { return { x: p1.x + p2.x, y: p1.y + p2.y }; }
js> var f1 = Function.withPositionalParameters(f, ["x","y"], ["x","y"]);
js> JSON.stringify(f1(1, 2, 3, 4));
{"x":4,"y":6}
js> function f(a, b, c) { return a + b * c; }
js> var f1 = Function.withNamedParameters(f);
js> var f2 = Function.withPositionalParameters(f1, ["a", "b", "c"]);
js> f2(1, 2, 3); // f2 is equivalent to (but slower than) f
7
js> // Reorder parameters
js> var f3 = Function.withPositionalParameters(f1, ["c", "b", "a"]);
js> f3(3, 2, 1);
7
*/
Function.withPositionalParameters = function(f, params /*, ... */) {
params = Array.prototype.slice.call(arguments, 1);
return function() {
var args = [];
var argumentsIndex = 0;
for (var i = 0; i < params.length; i++) {
var arg = {};
var paramList = params[i];
args.push(arg);
for (var p = 0; p < paramList.length; p++) {
arg[paramList[p]] = arguments[argumentsIndex];
++argumentsIndex;
}
}
return f.apply(this, args);
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment