Rest arguments allow one to write functions that take a variable number of arguments:
// This function sums its arguments. int sum(... int[] nums) { int total=0; for(int i=0; i < nums.length; ++i) total += nums[i]; return total; } sum(1,2,3,4); // returns 10 sum(); // returns 0 // This function subtracts subsequent arguments from the first. int subtract(int start ... int[] subs) { for(int i=0; i < subs.length; ++i) start -= subs[i]; return start; } subtract(10,1,2); // returns 7 subtract(10); // returns 10 subtract(); // illegal
Putting an argument into a rest array is called packing.
One can give an explicit list of arguments for the rest
argument, so subtract
could alternatively be implemented as
int subtract(int start ... int[] subs) { return start - sum(... subs); }
One can even combine normal arguments with rest arguments:
sum(1,2,3 ... new int[] {4,5,6}); // returns 21
This builds a new six-element array that is passed to sum
as
nums
. The opposite operation, unpacking, is not allowed:
subtract(... new int[] {10, 1, 2});
is illegal, as the start formal is not matched.
If no arguments are packed, then a zero-length array (as opposed to
null
) is bound to the rest parameter. Note that default
arguments are ignored for rest formals and the rest argument is not
bound to a keyword.
In some cases, keyword-only parameters are helpful to avoid arguments intended
for the rest parameter to be assigned to other parameters. For example, here
the use of keyword
is to avoid pnorm(1.0,2.0,0.3)
matching
1.0
to p
.
real pnorm(real keyword p=2.0 ... real[] v) { return sum(v^p)^(1/p); }
The overloading resolution in Asymptote
is similar to the
function matching rules used in C++. Every argument match is given a
score. Exact matches score better than matches with casting, and
matches with formals (regardless of casting) score better than packing
an argument into the rest array. A candidate is maximal if all of the
arguments score as well in it as with any other candidate. If there
is one unique maximal candidate, it is chosen; otherwise, there is an
ambiguity error.
int f(path g); int f(guide g); f((0,0)--(100,100)); // matches the second; the argument is a guide int g(int x, real y); int g(real x, int x); g(3,4); // ambiguous; the first candidate is better for the first argument, // but the second candidate is better for the second argument int h(... int[] rest); int h(real x ... int[] rest); h(1,2); // the second definition matches, even though there is a cast, // because casting is preferred over packing int i(int x ... int[] rest); int i(real x, real y ... int[] rest); i(3,4); // ambiguous; the first candidate is better for the first argument, // but the second candidate is better for the second one