I agree that we should have a way to call a variadic function with an Array at hand, without needing to take its elements apart (`foo(x[0], x[1], x[2])`) — which indeed is only practical when we statically know its length.
But I fear there's a shortcoming in this proposal that hasn't been addressed: How would the compiler clear the ambiguity in single-argument calls between existentials such as `Any` or `CustomStringConvertible` and sequences thereof (e.g. `[Any]` or `[CustomStringConvertible]`, which both can be treated as `Any` and `CustomStringConvertible` as well? If you take this function for example, func printThem(@variadic _ values: [Any]) then what would `values` be in the following calls, and why? printThem() // clearly [] printThem(1) // clearly [1] printThem(1, 2) // clearly [1, 2] printThem([1], [2]) // clearly [[1], [2]] printThem([]) // [] or [[]], which one? printThem([1]) // [1] or [[1]]? printThem([1, 2]) // [1, 2] or [[1, 2]]? I think it would be less painful a change (i.e. can be delayed past Swift 3) if we just augment what we have (the `...` argument declaration syntax) with a way to expand an Array in place of a variadic argument: func printThem(_ values: Any...) printThem(1) // values == [1] printThem([1]) // values == [[1]] // Possible expansion postfix syntax: printThem([1]...) // values == [1] // Expanding a non-array sequence: let things: Set<Int> = [1, 2, 3] printThem(Array(things)...) I think variadic functions are intended for human convenience and rarely used in performance-critical code, and it's probably more convenient that they're always passed as an Array, and not as a generic sequence. — Pyry Haravikk wrote: > For example, consider the following variadic function: > > func someMethod(_ values:Int...) { … } > Under this proposal the above can be rewritten as one of the following: > > func someMethod(@variadic _ values:[Int]) { … } // Basic Array solution > func someMethod(@variadic _ values:Foo) { … } // Foo is a custom > ArrayLiteralConvertible type > func someMethod<I:IteratorProtocol where I.Element == Int>(@variadic _ > values:I) { … } // Flexible, single-pass, generic solution > func someMethod<S:Sequence where S.Iterator.Element == Int>(@variadic _ > values:S) { … } // Flexible, (probably) multi-pass, generic solution > func someMethod<C:Collection where C.Iterator.Element == Int>(@variadic _ > values:C) { … } // Flexible, definitely multi-pass, indexed, generic solution > In this case the Iterator variation is preferred for greatest flexibility, > but it will depend upon the actual requirements of the method. Any of these > can be called as follows: > > someMethod([1, 2, 3, 4, 5, 6]) // normal array-literal call for any of the > above > someMethod(1, 2, 3, 4, 5, 6) // variadic call, synonymous with > array-literal call > someMethod(foo) // foo is an existing Array, Foo, Iterator, > Sequence or Collection variable as appropriate
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution