[swift-evolution] [Idea] Passing an Array to Variadic Functions

Radosław Pietruszewski radexpl at gmail.com
Mon Apr 18 14:09:22 CDT 2016


I think it’s pretty clear that if we have a syntax for passing an array to a variadic argument it should be:

	func(array…)

This would be symmetric with variadic type signature, and similar to how other languages do it (i.e. in Ruby, declaration is `*args` and array splat is also `*args`). The operator is necessary for disambiguation (in the `Any…` case and the like).

My guess is that it just hasn’t been implemented, but if we get a formal proposal, then maybe we can put it to review and then it shouldn’t be hard to get it implemented in Swift 3.0 timeframe.

The `…` operator would also be great in a different, but similar case — tuple splat, i.e. if you have a function `(T, U) -> Whatever`, and a tuple `(T, U)`, you could pass it to the function using `function(tuple…)`. (Implicit tuple splat was removed…)

Best,
— Radek

> On 17 Apr 2016, at 19:12, Justin Jia via swift-evolution <swift-evolution at swift.org> wrote:
> 
> Hi!
> 
> Currently, we can’t call a variadic function with an array of arguments.
> 
> Reference:
> 1. http://stackoverflow.com/questions/24024376/passing-an-array-to-a-function-with-variable-number-of-args-in-swift <http://stackoverflow.com/questions/24024376/passing-an-array-to-a-function-with-variable-number-of-args-in-swift>
> 2. https://www.drivenbycode.com/the-missing-apply-function-in-swift/ <https://www.drivenbycode.com/the-missing-apply-function-in-swift/>
> 
> Consider the following use case:
> 
> ```
> func average(numbers: Double…) -> Double {
>    return sum(numbers) / numbers.count // Error: Cannot convert value of type ‘[Double]’ to expected argument type ‘Double'
> }
> 
> func sum(numbers: Double...) -> Double { … }
> ```
> 
> Right now, there are two ways to fix it:
> 
> 1. Add another function that accept `[Double]` as input.
> 
> ```
> func average(numbers: Double…) -> Double {
>    return sum(numbers) / numbers.count
> }
> 
> func sum(numbers: Double...) -> Double {
>    return sum(numbers)
> }
> 
> func sum(numbers: [Double]) -> Double { … }
> ```
> 
> 2. Implement an `apply()` function using `unsafeBitCast`.
> 
> ```
> func average(numbers: Double…) -> Double {
>    return sum(apply(numbers)) / numbers.count
> }
> 
> func sum(numbers: [Double]) -> Double { … }
> 
> func apply<T, U>(fn: (T...) -> U, args: [T]) -> U {
>    typealias FunctionType = [T] -> U
>    return unsafeBitCast(fn, FunctionType.self)(args)
> }
> ```
> 
> However, both solutions are not very elegant. The first solution requires the library author to implement both functions, and the second solution breaks the guarantees of Swift’s type system.
> 
> Swift should allow passing an array to variadic functions, or we should somehow implement a type-safe `apply()` function in the standard library.
> 
> Justin
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160418/8182b30c/attachment.html>


More information about the swift-evolution mailing list