I agree that something needs to be done about this, because I quite frequently find myself weighing the pros/cons between allowing variadics and also writing the boilerplate to allow both variadics for developer friendliness and arrays for more dynamic usability. I generally find myself doing something like this:
class HelloWorld {
var names: [String]
// This becomes ambiguous with the variadic, so just remove it
// init(_ name: String) {
// names = [name]
// }
init(names: [String]) {
self.names = names
}
convenience init(_ names: String...) {
self.init(names: names)
}
func sayHello() {
names.forEach { print("Hello \($)") }
}
}
This allows me to write:
let hello = HelloWorld("Jacob", "Tim", "Steve")
hello.sayHello()
As well as use this dynamically:
class Goodbye {
var hello: HelloWorld
init(_ names: String...) {
// Cannot initialize using the variadic since names is converted to an array
hello = HelloWorld(names: names)
}
func sayGoodbye() {
hello.names.forEach { print("Goodbye \($0)") }
}
}
This is a poor example since in this case you would just subclass HelloWorld
and add the sayGoodbye()
function, however, it still demonstrates the principle that causes a lot of developers headache. We need splatting (or something else) to unify variadics and Collection
or Sequence
types. This would eliminate boilerplate code many of us are forced to use right now if we want both the variadic simplicity and array dynamic usability.
I also don't like how we are limited to only 1 variadic argument per function. Solving the issue in this pitch would remove that restriction.
I'm in favor of auto-splatting variadics into their corresponding Collection
/Sequence
type (so that this could work with both Array
s and Set
s), but that's because I've only every seen that (since I've programmed in Ruby). I am definitely open to other suggestions that may possibly be better.
It would be nice to keep the ...
syntax rather than needing to use an @variadic
attribute at the function parameter site.
If we could turn variadics into something like this:
class HelloWorld {
var names: Set<String>
init(_ names: Set<String>...) {
}
}
And then the compiler knows that names is either a Set<String>
or a variadic to be converted to a Set<String>
that would be great. If you wanted an Array<String>
then you'd say [String]...
instead.