posted 18 years ago
Here are my notes about varags in Tiger:
1- Defition:
void m1(T1 p1, T2... p2) {// use p2[]}
2- At most one vararg and as the last
3- An array can be passed when a vararg is expected.
4- To avoid this automatic conversion
of arrays cast them:
f(Object...) {}
T[] t;
f(t) --> f(t[0], t[1], ...)
f((Object)t)--> f(t)
Ambiguity:
==========
5- f(S, T...) conflicts with f(S, T[]), can't be defined together.
6- f(S, T, T...) doesn't conflict with f(S, T...)
However, only the following calls are allowed:
f(s); // the second
f(s, t[]); // the second
f(s, t, t[]); // the first
while the following are not
f(s, t)
f(s, t, t)
f(s, t, t, t) and so on
7- f(S, T...) doesn't conflict with f(S, T): f(s, t) resolves to the
latter, and other calls (for 0 or 2 or more t paramters) to the former
8- In general f(S, T...) doesn't conflict with f(S, T, T, T): the
latter reserves the call with 3 T parameters and the former reserves
the rest.
9- A call is resolved first in favor of the exact parameters-count
match then in favor of best type match.
A <|-- B <|-- C
f(A), f(B...b):f(new B()) resolves to f(A)
f(A...a), B(B...b): f(new C()); resolves to f(B...b)
10- This has nothing to do with varargs:
if B extends A and implements I then the call is ambiguous:
f(A), f(I): f(new B()); it needs A cast to determine!
11- f(int...), f(double...) doesn't conflict, but f(i,j,..) is
- Ambiguous if all params are integrals or integral literals.
- Matchs the latter if one parameter is a double or a double literal.
The only way to invoke the former is f(int[]);