[Proposal] Allow passing a variadic parameter to another variadic function


(Christopher Boyd) #1

Currently, Swift doesn't have a way to easily pass a variadic parameter to
another variadic function because the variadic parameter itself has already
been collected into an array.

There was a prior posting a few weeks back about allowing arrays to be
passed to a variadic parameter which would resolve this very specific issue:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160411/015185.html

Unfortunately, that thread devolved into an argument on whether or not
variadic parameters should be removed entirely.

I, certainly, see merit in having functions that can accept a variable
number of arguments and variadic functions should seem intuitive to anyone
else that might be reading the code.

Swift's documentation presents a very intuitive example:

   1. arithmeticMean(1, 2, 3, 4, 5)

It's obvious what this function is doing, and any intelligent person would
expect 3 as the result. Even WolframAlpha knows how to interpret this:
http://www.wolframalpha.com/input/?i=arithmeticMean(1,+2,+3,+4,+5)

Moreover, a function can only have ONE variadic parameter, which I think
reduces any possible confusion.

Regardless, if variadic parameters are going to stay in Swift, then I think
they should at least support chaining to another function.

The most obvious way of allowing this would be to allow variadic parameters
to accept an array.

However, I think that if an array (of the parameter type) is specified for
a variadic parameter, then no other values should be allowed. This
eliminates any unnecessary complexity of potentially having to add values
to the array.

- Christopher Boyd


(Ricardo Parada) #2

Hi Christopher,

Do you think something like this would work if there was a #splat() magic operator like this:

let values = [1, 2, 3, 4, 5]
let mean = arithmeticMean(#splat(values))

···

On May 20, 2016, at 11:19 AM, Christopher Boyd via swift-evolution <swift-evolution@swift.org> wrote:

Currently, Swift doesn't have a way to easily pass a variadic parameter to another variadic function because the variadic parameter itself has already been collected into an array.

There was a prior posting a few weeks back about allowing arrays to be passed to a variadic parameter which would resolve this very specific issue:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160411/015185.html

Unfortunately, that thread devolved into an argument on whether or not variadic parameters should be removed entirely.

I, certainly, see merit in having functions that can accept a variable number of arguments and variadic functions should seem intuitive to anyone else that might be reading the code.

Swift's documentation presents a very intuitive example:
arithmeticMean(1, 2, 3, 4, 5)
It's obvious what this function is doing, and any intelligent person would expect 3 as the result. Even WolframAlpha knows how to interpret this: http://www.wolframalpha.com/input/?i=arithmeticMean(1,+2,+3,+4,+5)

Moreover, a function can only have ONE variadic parameter, which I think reduces any possible confusion.

Regardless, if variadic parameters are going to stay in Swift, then I think they should at least support chaining to another function.

The most obvious way of allowing this would be to allow variadic parameters to accept an array.

However, I think that if an array (of the parameter type) is specified for a variadic parameter, then no other values should be allowed. This eliminates any unnecessary complexity of potentially having to add values to the array.

- Christopher Boyd
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Christopher Boyd) #3

Ricardo,

That'd work, but I was thinking more along the lines of:
- func add(numbers: Double...) -> Double {
- var total: Double = 0
- for number in numbers {
- total += number
- }
- return total
- }
- func arithmeticMean(numbers: Double...) -> Double {
- return add(numbers) / Double(numbers.count)
- }

Certainly, #splat would work, but it may be slightly more confusing to
someone that hasn't seen the splat operator before:
- func arithmeticMean(numbers: Double...) -> Double {
- return add(#splat(numbers)) / Double(numbers.count)
- }

···

On Fri, May 20, 2016 at 11:52 AM Ricardo Parada <rparada@mac.com> wrote:

Hi Christopher,

Do you think something like this would work if there was a #splat() magic
operator like this:

let values = [1, 2, 3, 4, 5]
let mean = arithmeticMean(#splat(values))

On May 20, 2016, at 11:19 AM, Christopher Boyd via swift-evolution < > swift-evolution@swift.org> wrote:

Currently, Swift doesn't have a way to easily pass a variadic parameter to
another variadic function because the variadic parameter itself has already
been collected into an array.

There was a prior posting a few weeks back about allowing arrays to be
passed to a variadic parameter which would resolve this very specific issue:

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160411/015185.html

Unfortunately, that thread devolved into an argument on whether or not
variadic parameters should be removed entirely.

I, certainly, see merit in having functions that can accept a variable
number of arguments and variadic functions should seem intuitive to anyone
else that might be reading the code.

Swift's documentation presents a very intuitive example:

   1. arithmeticMean(1, 2, 3, 4, 5)

It's obvious what this function is doing, and any intelligent person would
expect 3 as the result. Even WolframAlpha knows how to interpret this:
http://www.wolframalpha.com/input/?i=arithmeticMean(1,+2,+3,+4,+5)

Moreover, a function can only have ONE variadic parameter, which I think
reduces any possible confusion.

Regardless, if variadic parameters are going to stay in Swift, then I
think they should at least support chaining to another function.

The most obvious way of allowing this would be to allow variadic
parameters to accept an array.

However, I think that if an array (of the parameter type) is specified for
a variadic parameter, then no other values should be allowed. This
eliminates any unnecessary complexity of potentially having to add values
to the array.

- Christopher Boyd

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Vladimir) #4

[offtopic]

···

On 20.05.2016 19:08, Christopher Boyd via swift-evolution wrote:

Certainly, #splat would work, but it may be slightly more confusing to
someone that hasn't seen the splat operator before:

So, he/she will open swift documentation or drop the question to google once, and from that moment will know what #splat means.
[/offtopic]


(Christopher Boyd) #5

Vladimir,

True, but does the extra syntax actually accomplish anything?

From my example:

   - func arithmeticMean(numbers: Double...) -> Double {
   - return add(numbers) / Double(numbers.count)
   - }

It's clear that the intent is to pass all the numbers to add().

What, exactly, does adding the #splat() syntax achieve? It doesn't add any
additional clarity.

Moreover, I don't think #splat has been accepted as a proposal yet.

···

On Fri, May 20, 2016 at 12:19 PM Vladimir.S <svabox@gmail.com> wrote:

[offtopic]
On 20.05.2016 19:08, Christopher Boyd via swift-evolution wrote:
> Certainly, #splat would work, but it may be slightly more confusing to
> someone that hasn't seen the splat operator before:
So, he/she will open swift documentation or drop the question to google
once, and from that moment will know what #splat means.
[/offtopic]


(Christopher Boyd) #6

Jaden,

In that very specific example with generics, couldn't you just explicitly
specify foo<[T]>(bar: bar)?

···

On Fri, May 20, 2016 at 12:39 PM <jaden.geller@gmail.com> wrote:

Without it, there could be ambiguity. Observe:

func foo<T>(bar: [T]...) {
  foo(bar: bar) // splat or pass single arg?
}

- Jaden Geller
Sent from my iPhone

On May 20, 2016, at 9:29 AM, Christopher Boyd via swift-evolution < > swift-evolution@swift.org> wrote:

Vladimir,

True, but does the extra syntax actually accomplish anything?

From my example:

   - func arithmeticMean(numbers: Double...) -> Double {
   - return add(numbers) / Double(numbers.count)
   - }

It's clear that the intent is to pass all the numbers to add().

What, exactly, does adding the #splat() syntax achieve? It doesn't add
any additional clarity.

Moreover, I don't think #splat has been accepted as a proposal yet.

On Fri, May 20, 2016 at 12:19 PM Vladimir.S <svabox@gmail.com> wrote:

[offtopic]
On 20.05.2016 19:08, Christopher Boyd via swift-evolution wrote:
> Certainly, #splat would work, but it may be slightly more confusing to
> someone that hasn't seen the splat operator before:
So, he/she will open swift documentation or drop the question to google
once, and from that moment will know what #splat means.
[/offtopic]

_______________________________________________

swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Christopher Boyd) #7

Jaden,

That's a good point.

In C#, variadic parameters explicitly stated to be arrays.

This means that in C#, this never occurs because:
foo(params int[] bar)
has the same signature as
foo(int[] bar)

Thus, you can't have both commands defined as they're identified to be
conflicting overloads. In fact, it's what allows you to simply pass an int
array to foo(params int[] bar).

The params keyword basically just specifies to be an accumulator for
multiple parameters.

Meanwhile, in Swift you can have a single class with all of the following:
foo(bar: Int)
foo(bar: Int...)
foo(bar: [Int])

For the syntax to work without a #splat operator, methods with Int... and
[Int] would have to be considered as equivalent signatures.

···

On Fri, May 20, 2016 at 12:56 PM <jaden.geller@gmail.com> wrote:

Sure, but imagine it weren't generics. Instead, we have two specialized
functions, the first identical the generic one with T = Int and the second
with T = [Int]. We have the same problem again.

Jaden

On May 20, 2016, at 9:50 AM, Christopher Boyd <xpboyd@gmail.com> wrote:

Jaden,

In that very specific example with generics, couldn't you just explicitly
specify foo<[T]>(bar: bar)?

On Fri, May 20, 2016 at 12:39 PM <jaden.geller@gmail.com> wrote:

Without it, there could be ambiguity. Observe:

func foo<T>(bar: [T]...) {
  foo(bar: bar) // splat or pass single arg?
}

- Jaden Geller
Sent from my iPhone

On May 20, 2016, at 9:29 AM, Christopher Boyd via swift-evolution < >> swift-evolution@swift.org> wrote:

Vladimir,

True, but does the extra syntax actually accomplish anything?

From my example:

   - func arithmeticMean(numbers: Double...) -> Double {
   - return add(numbers) / Double(numbers.count)
   - }

It's clear that the intent is to pass all the numbers to add().

What, exactly, does adding the #splat() syntax achieve? It doesn't add
any additional clarity.

Moreover, I don't think #splat has been accepted as a proposal yet.

On Fri, May 20, 2016 at 12:19 PM Vladimir.S <svabox@gmail.com> wrote:

[offtopic]
On 20.05.2016 19:08, Christopher Boyd via swift-evolution wrote:
> Certainly, #splat would work, but it may be slightly more confusing to
> someone that hasn't seen the splat operator before:
So, he/she will open swift documentation or drop the question to google
once, and from that moment will know what #splat means.
[/offtopic]

_______________________________________________

swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution