Function arity is the number of arguments a function expects. While it sounds very theoretical, it’s actually quite useful in practice, especially in functional programming.
Getting the arity of a function
The arity of a function can be easily retrieved using Function.prototype.length
.
代码实现
const arity = fn => fn.length;
arity(Math.sqrt); // 1
arity(Math.pow); // 2
arity((x, y, z) => x + y + z); // 3
arity((...args) => args); // 0
As you can see in the example above, the arity of a function is the number of parameters it expects. This is true for regular functions but not for variadic functions. A variadic function is a function that accepts a variable number of arguments. In that case, Function.prototype.length
will return 0
.
Creating a function with a fixed arity
In some cases, we might want to limit the number of arguments a function can accept. This comes in handy for variadic functions, especially when combined with currying.
Nullary function arity
A nullary function is a function that accepts no arguments. In that case, we can simply call the function without any arguments.
使用样例
const nullary = fn => () => fn();
nullary(Math.random)(); // 0.6019623086
Unary function arity
A unary function is a function that accepts exactly one argument and can be created by calling the function with just the first argument provided.
const unary = fn => val => fn(val);
['6', '8', '10'].map(unary(Number.parseInt)); // [6, 8, 10]
Binary function arity
A binary function is a function that accepts exactly two arguments. Similarly to the unary function, we can create a binary function by calling the function with just the first two arguments provided.
const binary = fn => (a, b) => fn(a, b);
['2', '1', '0'].map(binary(Math.max)); // [2, 1, 2]
N-ary function arity
In general, a n-ary function is a function that accepts exactly n
arguments. Using Array.prototype.slice()
and the spread operator (...
), we can create a function that will call the provided function with the first n
arguments.
const nAry = (fn, n) => (...args) => fn(...args.slice(0, n));
const firstTwoMax = nAry(Math.max, 2);
[[2, 6, 'a'], [6, 4, 8], [10]].map(x => firstTwoMax(...x)); // [6, 6, 10]
Converting array-accepting functions to variadic functions
In some cases, it might be easier to convert a function that accepts an array of arguments into a variadic function. Or, perhaps, we might want to do the opposite. Using the spread operator (...
), and rest arguments, this is quite straightforward.
const toVariadic = fn => (...args) => fn(args);
const fromVariadic = fn => args => fn(...args);
const allPromises = toVariadic(Promise.all.bind(Promise));
let p1 = Promise.resolve(1);
let p2 = Promise.resolve(2);
allPromises(p1, p2).then(console.log); // LOGS: [1, 2]
const arrayMax = fromVariadic(Math.max);
arrayMax([1, 2, 3]); // 3