6.12.2 Named arguments

It is sometimes difficult to remember the order in which arguments appear in a function declaration. Named (keyword) arguments make calling functions with multiple arguments easier. Unlike in the C and C++ languages, an assignment in a function argument is interpreted as an assignment to a parameter of the same name in the function signature, not within the local scope. The command-line option -d may be used to check Asymptote code for cases where a named argument may be mistaken for a local assignment.

When matching arguments to signatures, first all of the keywords are matched, then the arguments without names are matched against the unmatched formals as usual. For example,

int f(int x, int y) {
  return 10x+y;
}
write(f(4,x=3));

outputs 34, as x is already matched when we try to match the unnamed argument 4, so it gets matched to the next item, y.

For the rare occasions where it is desirable to assign a value to local variable within a function argument (generally not a good programming practice), simply enclose the assignment in parentheses. For example, given the definition of f in the previous example,

int x;
write(f(4,(x=3)));

is equivalent to the statements

int x;
x=3;
write(f(4,3));

and outputs 43.

Parameters can be specified as “keyword-only” by putting keyword immediately before the parameter name, as in int f(int keyword x) or int f(int keyword x=77). This forces the caller of the function to use a named argument to give a value for this parameter. That is, f(x=42) is legal, but f(25) is not. Keyword-only parameters must be listed after normal parameters in a function definition.

As a technical detail, we point out that, since variables of the same name but different signatures are allowed in the same scope, the code

int f(int x, int x()) {
  return x+x();
}
int seven() {return 7;}

is legal in Asymptote, with f(2,seven) returning 9. A named argument matches the first unmatched formal of the same name, so f(x=2,x=seven) is an equivalent call, but f(x=seven,2) is not, as the first argument is matched to the first formal, and int () cannot be implicitly cast to int. Default arguments do not affect which formal a named argument is matched to, so if f were defined as

int f(int x=3, int x()) {
  return x+x();
}

then f(x=seven) would be illegal, even though f(seven) obviously would be allowed.