<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><span></span></div><div><meta http-equiv="content-type" content="text/html; charset=utf-8"><div>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.</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature">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?</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature">If you take this function for example,</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature"> func printThem(@variadic _ values: [Any])</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature">then what would `values` be in the following calls, and why?</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature"> printThem() // clearly []</div><div id="AppleMailSignature"> printThem(1) // clearly [1]</div><div id="AppleMailSignature"> printThem(1, 2) // clearly [1, 2]</div><div id="AppleMailSignature"> printThem([1], [2]) // clearly [[1], [2]]</div><div id="AppleMailSignature"> printThem([]) // [] or [[]], which one?</div><div id="AppleMailSignature"> printThem([1]) // [1] or [[1]]?</div><div id="AppleMailSignature"> printThem([1, 2]) // [1, 2] or [[1, 2]]?</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature">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:</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature"> func printThem(_ values: Any...)</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature"> printThem(1) // values == [1]</div><div id="AppleMailSignature"> printThem([1]) // values == [[1]]</div><div id="AppleMailSignature"> // Possible expansion postfix syntax:</div><div id="AppleMailSignature"> printThem([1]...) // values == [1]</div><div id="AppleMailSignature"> // Expanding a non-array sequence:</div><div id="AppleMailSignature"> let things: Set<Int> = [1, 2, 3]</div><div id="AppleMailSignature"> printThem(Array(things)...)</div><div><br></div><div>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.</div><div><br></div><div>— Pyry</div><div><br>Haravikk wrote:<br><br></div><blockquote type="cite"><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class="">For example, consider the following variadic function:</p><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; word-wrap: normal; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; overflow: visible; line-height: inherit; word-wrap: normal;" class="">func someMethod(_ values:Int...) { … }
</code></pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class="">Under this proposal the above can be rewritten as one of the following:</p><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; word-wrap: normal; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; overflow: visible; line-height: inherit; word-wrap: normal;" class="">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
</code></pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class="">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:</p><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; word-wrap: normal; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; overflow: visible; line-height: inherit; word-wrap: normal;" class="">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</code></pre></blockquote></div></body></html>