Until now variadic parameters seemed obvious for me. But consider such code:
stdOut.writeLine("hello","world"); list.append('a','b','c'); let arr = Array<Int>(data:1,2,3);
Looks fine (Skila has also shorter syntax for arrays, similar to Swift). But since all three methods are defined with variadic parameter let’s remove arguments:
stdOut.writeLine(); list.append(); let arr = Array<Int>();
Still technically valid, yet there is something off with the second call — what is the point of appending nothing to the list? I noticed it, however it looked like a corner case at the time, something not perfect but not worth worrying about so I moved on.
But recently I had trouble with overriding methods (Skila does not have explicit overriding, yet). For example with existing constructor for `Array
`:
def init(data: T ...) // body of the method end
it is impossible to define default parameterless constructor. The straw was broken — I had to find out the nature of the problem. As it appeared, it is the dual perspective of variadic parameter. One side is what we pass, and the second side is what we get. If we got no data at all from parameter, does it mean user passed empty “bag” of data, or no data at all?
Obviously there are two notions and both need to be reflected in semantics of the language because both are useful — Skila currently supports such definitions as:
// can be called with no arguments def writeLine<T>(s T ?...) // code goes on // has to be called with at least one argument def append(elem T ...) // code goes on
Please notice you can still call `append
` with argument having no data in it, but there has to be something between parentheses of the call.
And as a reminder — this feature is not a replacement of variadic limits. For example with only limits, you cannot express `append
` as above. Compare:
def append(elem T 1...)
Such code works the same for explicit arguments, but not for splatted (unpacked) collections:
let a = 5; let xx = Array<Int>(data:1,2,3); let yy = Array<Int>(); list.append(a); list.append(xx/...); // splat operator list.append(yy/...);
On the last call you will get exception (in run time), because `append
` with limits requires on the callee side at least one element of data. Such definition of `append
` is not robust for real use.