[Idea] Passing an Array to Variadic Functions

Cons of removing variadic functions:
1. More verbose syntax.
2. Break old code.

The verbosity is only two characters (square brackets), and it needn’t break old code:

  Before: func myFunc(values:Foo…)
  After: func myFunc(values:[Foo])

  Before: myFunc(foo, bar, baz)
  After: myFunc([foo, bar, baz])

Currently variadic functions just produce an array of arguments anyway, so simply translating call-sites to pass in an array guarantees compatibility.

···

On 19 Apr 2016, at 20:25, Justin Jia <justin.jia.developer@gmail.com> wrote:

On Apr 19, 2016, at 10:54 AM, Haravikk <swift-evolution@haravikk.me <mailto:swift-evolution@haravikk.me>> wrote:

On 19 Apr 2016, at 17:51, Vladimir.S <svabox@gmail.com <mailto:svabox@gmail.com>> wrote:

I.e. the question is *if we want/need to be able to pass array to existed variadic function*. Not about removing the variadic feature("removing" is offtop for this poposal, as I understand)

I’d say it’s on-topic, as removing variadic functions would eliminate the problem entirely, so if it is considered a better alternative then there would be no need to have an additional means of calling them with an array of arguments.

Personally the way I see it comes down to variadic functions is this:

Pros:
Slightly cleaner syntax at call-site.
Possibly optimisations unavailable to Array passing?

Cons:
Doesn’t do anything that passing an array directly can’t.
Passing an array is actually slightly more flexible (can dynamically pass more or less arguments as required at the call site).
Less explicit type at call site; gives the appearance of passing instance(s) of Foo, rather than one instance of [Foo], can lead to ambiguity with overloaded functions.
Extra syntax to support (enabling array passing would be more code required to support this feature)

I’d also argue that variadic functions increase the learning curve, as the first time you’re presented with one it isn’t necessarily clear what it does unless you’ve encountered them before. Like I say it can be ambiguous at the call-site in particular, as it doesn’t show that an array of [Foo] is being passed as opposed to N instances of Foo (however many are in the call).

While I’ve used them in the past, I’ve never really felt that they simplify anything enough to justify them, as it’s just two square brackets extra to pass an array; this is extra noise sure, but clarifies what is actually happening.

So if variadic functions don’t have any other advantages, then it’s really just a very minor piece of syntactic sugar that can lead to more confusion, less explicit types in function calls, an extra piece of syntax to parse and handle and possibly other features required to support it better (like the one being inquired about). The only other argument I can think of for them is that many other languages have them, but that’s not important to me vs cutting out cruft.

Short version; removing variadic functions would solve the problem of defining overloads for both variadic and array types by only ever requiring the latter.

P.S- I’d also like to note that where possible people should be accepting Sequences or Collections in their methods anyway rather than arrays specifically, as it’s more flexible that way :wink:

Would that require some compiler magic, i.e.

>
> foo(#splat(arr))

Probably yes. Although passing array to variadic func IMO is must-have feature, I don't think it will be used very often, so using of such compiler magic seems OK at the moment when we need this.

Also this solves the problem that passing array to variadic func is confusing about the arguments of function. If just pass array to such function - it is not clear what parameters of the function, is it variadic or "usual" function, is array just first argument or each value in array is argument.

The #splat solution is explicit, clearly mark function as variadic and array as a collection of parameters, it is *obvious* what is going there.

And as it is compiler business(at the compilation time) to interpret "arr" as a source of arguments for function - I think #splat is a correct solution.

To @Justin: I suggest to include this solution to the proposal.

···

On 20.04.2016 2:07, Ricardo Parada wrote:

On Apr 19, 2016, at 12:51 PM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

I suggest to look at the subject of this thread and initial proposal:
"Swift should allow passing an *array to variadic functions*, or we should implement a type-safe `apply()` function in the standard library."

I.e. the question is *if we want/need to be able to pass array to existed variadic function*. Not about removing the variadic feature("removing" is offtop for this poposal, as I understand)

For example we have:
func foo(x: Int ...) {..}

and later in code we have
var arr : [Int] = getSomehow()

Should we be able to call foo in this way:

foo(arr)

Or how we can call foo(..) about array of values, not values as list of parameters.

On 19.04.2016 19:34, Jeremy Pereira via swift-evolution wrote:

On 19 Apr 2016, at 07:51, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

I think the question really is whether not having to add square brackets is really enough to justify a whole language feature? Basically you’ve got two ways you could do this:

No, that’s not the question. The question is whether the downside to variadic parameters is really enough to justify _removing_ an existing language feature.

The burden of justification should be on those people wanting to change the language, not on those wanting to maintain the status quo and “I don’t like it” or “I think it makes code a tiny bit less readable” is not sufficient justification, in my opinion because you already have the option not to use the feature. Whereas, if you remove the feature, those people of the opinion “it makes code a tiny bit more readable” have nowhere to go.

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

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

At this moment I think we should keep "variadic" feature just because it is very handy and useful practically, in our day-by-day coding. Without it we'll have to write a number of overloaded functions or use [] all the time.
I.e. I believe nobody wants to write
print([i])
print(["hello"])
print([i,j])
, and for this we'll need declarations
print(:slight_smile:
print(::slight_smile:
print(:::slight_smile:
..
print([])

Plus, array of values is not the same as a list of parameters at the end. Using of array instead of parameters probably confuses more than variadic parameters for the same function name.

So, the cons of having variadic functions are much less than the pros.

But +1 to be able to use array as parameters by using some #splat compiler-time func, i.e. print(#splat(arr)) - explicit and clear

···

On 19.04.2016 22:25, Justin Jia wrote:

Pros of removing variadic functions:
1. Slightly easier to understand.
2. Simpler language design.

Cons of removing variadic functions:
1. More verbose syntax.
2. Break old code.

I understand your reasons. But,

1. People have been using NSLog and StringWithFormat for many years and
most people don't have any difficulty understanding them. So the benefit of
removing this feature is very subtle.
2. The solution I proposed to fix is very straightforward. I don't think it
will too much cost. (Maybe we need someone who is familiar with compiler to
compare the cost).

Also,

1. Sometimes we need simpler syntax. Like this project:
https://github.com/JustinJiaDev/SwiftShell
I prefer to write ls(.all, .longFormat) instead of ls([.all, .longFormat]).
That's really important if we want to use it as a shell.
2. It not only breaks the language itself, it will also break cocoa APIs.
That is bad.

Justin

On Apr 19, 2016, at 10:54 AM, Haravikk <swift-evolution@haravikk.me > <mailto:swift-evolution@haravikk.me>> wrote:

On 19 Apr 2016, at 17:51, Vladimir.S <svabox@gmail.com >>> <mailto:svabox@gmail.com>> wrote:

I.e. the question is *if we want/need to be able to pass array to
existed variadic function*. Not about removing the variadic
feature("removing" is offtop for this poposal, as I understand)

I’d say it’s on-topic, as removing variadic functions would eliminate the
problem entirely, so if it is considered a better alternative then there
would be no need to have an additional means of calling them with an
array of arguments.

Personally the way I see it comes down to variadic functions is this:

*Pros*:

  * Slightly cleaner syntax at call-site.
  * Possibly optimisations unavailable to Array passing?

*Cons*:

  * Doesn’t do anything that passing an array directly can’t.
  * Passing an array is actually slightly more flexible (can dynamically
    pass more or less arguments as required at the call site).
  * Less explicit type at call site; gives the appearance of passing
    instance(s) of Foo, rather than one instance of [Foo], can lead to
    ambiguity with overloaded functions.
  * Extra syntax to support (enabling array passing would be more code
    required to support this feature)

I’d also argue that variadic functions increase the learning curve, as
the first time you’re presented with one it isn’t necessarily clear what
it does unless you’ve encountered them before. Like I say it can be
ambiguous at the call-site in particular, as it doesn’t show that an
array of [Foo] is being passed as opposed to N instances of Foo (however
many are in the call).

While I’ve used them in the past, I’ve never really felt that they
simplify anything enough to justify them, as it’s just two square
brackets extra to pass an array; this is extra noise sure, but clarifies
what is actually happening.

So if variadic functions don’t have any other advantages, then it’s
really just a very minor piece of syntactic sugar that can lead to more
confusion, less explicit types in function calls, an extra piece of
syntax to parse and handle and possibly other features required to
support it better (like the one being inquired about). The only other
argument I can think of for them is that many other languages have them,
but that’s not important to me vs cutting out cruft.

Short version; removing variadic functions would solve the problem of
defining overloads for both variadic and array types by only ever
requiring the latter.

P.S- I’d also like to note that where possible people should be accepting
Sequences or Collections in their methods anyway rather than arrays
specifically, as it’s more flexible that way :wink:

I suggest to look at the subject of this thread and initial proposal:

I suggest to look at the post to which I was replying to find out why I said what I said.

I.e. the question is *if we want/need to be able to pass array to existed variadic function*. Not about removing the variadic feature("removing" is offtop for this poposal, as I understand)

Take that up with Haravikk, not me, (or Howard Lovatt who first raised the possibility of removing the varargs feature on this thread).

···

On 19 Apr 2016, at 17:51, Vladimir.S <svabox@gmail.com> wrote:

We're in a stage of Swift's development where we can ask this question
fairly freely, and the fact that we expect to reach stability soon,
where it will be harder to ask the question, makes us ask it a bit more
often these days. It's a balance; we don't want to create arbitrary
language churn, but we also don't want to be forever stuck with
decisions we'll regret later.

···

on Wed Apr 20 2016, Tino Heth <swift-evolution@swift.org> wrote:

The question is whether the downside to variadic parameters is really enough to justify _removing_ an existing language feature.

The burden of justification should be on those people wanting to
change the language, not on those wanting to maintain the status quo
and “I don’t like it” or “I think it makes code a tiny bit less
readable” is not sufficient justification, in my opinion because you
already have the option not to use the feature.

Afaics, this isn't true:
Increment/decrement operators, currying, tuple splat and even the
C-style for loop have already been deprecated, and although I would
have preferred to keep some of those constructs, I think it is good
how progressive Swift is pushed forward ("would we add this feature
now if it wasn't already there?").

--
Dave

I think your lists are incomplete.

I’d say it’s on-topic, as removing variadic functions would eliminate the problem entirely, so if it is considered a better alternative then there would be no need to have an additional means of calling them with an array of arguments.

Personally the way I see it comes down to variadic functions is this:

Pros:
  • Slightly cleaner syntax at call-site.
  • Possibly optimisations unavailable to Array passing?

• Makes calling C and Objective-C functions with variadic parameters less confusing
• Will not break existing Swift code that uses variadic parameters
• Makes generalising some functions cleaner e.g. zip(a, b) could be generalised to any number of parameters as already mentioned, but if you instead used an array, we would end up with a massive thread about whether the original two parameter zip should be removed

Cons:
  • Doesn’t do anything that passing an array directly can’t.
  • Passing an array is actually slightly more flexible (can dynamically pass more or less arguments as required at the call site).
  • Less explicit type at call site; gives the appearance of passing instance(s) of Foo, rather than one instance of [Foo], can lead to ambiguity with overloaded functions.
  • Extra syntax to support (enabling array passing would be more code required to support this feature)

I’d also argue that variadic functions increase the learning curve,

You are coming at this from the wrong direction. You should be arguing that _removing_ variadic functions would _reduce_ the learning curve. This is true, but only something to worry about if the learning curve is currently too steep and needs reducing.

My quick and unscientific survey of questions and answers relating to variadic parameters on StackOverflow yields no instances of people asking what does the`…` in `func foo(a: Int…)` do which suggests that the learning curve is actually fairly trivial. However their is a megaton of questions asking things like “why can’t I pass an array" and "how do I forward variadic arguments to another variadic function".

P.S- I’d also like to note that where possible people should be accepting Sequences or Collections in their methods anyway rather than arrays specifically, as it’s more flexible that way :wink:

Now there’s an example of a steep learning curve in Swift 2.

···

On 19 Apr 2016, at 18:54, Haravikk <swift-evolution@haravikk.me> wrote:

The question is whether the downside to variadic parameters is really enough to justify _removing_ an existing language feature.

The burden of justification should be on those people wanting to
change the language, not on those wanting to maintain the status quo
and “I don’t like it” or “I think it makes code a tiny bit less
readable” is not sufficient justification, in my opinion because you
already have the option not to use the feature.

Afaics, this isn't true:
Increment/decrement operators, currying, tuple splat and even the
C-style for loop have already been deprecated, and although I would
have preferred to keep some of those constructs, I think it is good
how progressive Swift is pushed forward ("would we add this feature
now if it wasn't already there?").

We're in a stage of Swift's development where we can ask this question
fairly freely, and the fact that we expect to reach stability soon,

I should clarify that this is true for a sufficiently-nebulous
definition of “soon.” :slight_smile:

···

on Wed Apr 20 2016, Dave Abrahams <swift-evolution@swift.org> wrote:

on Wed Apr 20 2016, Tino Heth <swift-evolution@swift.org> wrote:

where it will be harder to ask the question, makes us ask it a bit
more often these days. It's a balance; we don't want to create
arbitrary language churn, but we also don't want to be forever stuck
with decisions we'll regret later.

--
Dave

Possibly optimisations unavailable to Array passing?

Indeed, it should be possible to implement varargs by allocating the argument array on the stack (and having the compiler implicitly copy it to the heap inside the callee if it escapes). Although you can imagine this type of optimization being performed for arbitrary arrays, it would be more difficult and less predictable.

Slava

···

On Apr 19, 2016, at 10:54 AM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

Cons:
Doesn’t do anything that passing an array directly can’t.
Passing an array is actually slightly more flexible (can dynamically pass more or less arguments as required at the call site).
Less explicit type at call site; gives the appearance of passing instance(s) of Foo, rather than one instance of [Foo], can lead to ambiguity with overloaded functions.
Extra syntax to support (enabling array passing would be more code required to support this feature)

I’d also argue that variadic functions increase the learning curve, as the first time you’re presented with one it isn’t necessarily clear what it does unless you’ve encountered them before. Like I say it can be ambiguous at the call-site in particular, as it doesn’t show that an array of [Foo] is being passed as opposed to N instances of Foo (however many are in the call).

While I’ve used them in the past, I’ve never really felt that they simplify anything enough to justify them, as it’s just two square brackets extra to pass an array; this is extra noise sure, but clarifies what is actually happening.

So if variadic functions don’t have any other advantages, then it’s really just a very minor piece of syntactic sugar that can lead to more confusion, less explicit types in function calls, an extra piece of syntax to parse and handle and possibly other features required to support it better (like the one being inquired about). The only other argument I can think of for them is that many other languages have them, but that’s not important to me vs cutting out cruft.

Short version; removing variadic functions would solve the problem of defining overloads for both variadic and array types by only ever requiring the latter.

P.S- I’d also like to note that where possible people should be accepting Sequences or Collections in their methods anyway rather than arrays specifically, as it’s more flexible that way :wink:
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Sorry for my absence.

Increment/decrement operators, currying, tuple splat and even the C-style for loop have already been deprecated, and although I would have preferred to keep some of those constructs, I think it is good how progressive Swift is pushed forward ("would we add this feature now if it wasn't already there?”)

That is exactly my opinion.

Thanks Haravikk for compiling a list with pros/cons.

In my opinion, we have a perfectly fine way to express “a sequence of values”. And that is arrays. So why would you need a second concept to accomplish the exact same thing? In fact, inside the implementing function all varargs *are* arrays, why aren’t they outside?

The other reason I don’t like them is that, at the call site, you cannot distinguish between them and C functions (or badly named Swift functions).

Take the C stdlib atan2 function for example:

let a = atan2(3.0, 4.0)

Does it take 2 Doubles? Or does it take a vararg list of Doubles. Can I do let a = atan2(3.0, 4.0, 5.0)? I cannot tell by reading someone else’s code (and there is quite a lot of C code out there).

Even in Swift it is possible to write functions like these:

func whichOne(t: Int) -> Int {
  return 1
}

func whichOne(t: Int...) -> Int {
  return 2
}

func whichOne(t: Int, _ t2: Int...) -> Int {
  return 3
}

Now call these functions:

whichOne(1)
whichOne(2, 2)
whichOne(3, 3)

Can you guess what they return? (answer: 1,3,3)

In the end it’s just another concept to learn (or at least to be aware of) which in and of itself does not create much of an added value (except you save two characters []).

- Dennis

···

On Apr 20, 2016, at 4:56 PM, Tino Heth via swift-evolution <swift-evolution@swift.org> wrote:

The question is whether the downside to variadic parameters is really enough to justify _removing_ an existing language feature.

The burden of justification should be on those people wanting to change the language, not on those wanting to maintain the status quo and “I don’t like it” or “I think it makes code a tiny bit less readable” is not sufficient justification, in my opinion because you already have the option not to use the feature.

Afaics, this isn't true:

The value of variadic functions is imho less than the possibility to omit "()" in procedure calls, and afair, there have been several posts that illustrate the complications of this feature.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

The question is whether the downside to variadic parameters is really enough to justify _removing_ an existing language feature.

The burden of justification should be on those people wanting to change the language, not on those wanting to maintain the status quo and “I don’t like it” or “I think it makes code a tiny bit less readable” is not sufficient justification, in my opinion because you already have the option not to use the feature.

Afaics, this isn't true:
Increment/decrement operators, currying, tuple splat and even the C-style for loop have already been deprecated, and although I would have preferred to keep some of those constructs, I think it is good how progressive Swift is pushed forward ("would we add this feature now if it wasn't already there?”).

How do these examples show that the burden of justification should not be on those people making the change? I have not claimed that language features should never be removed, only that removal needs some sort of real justification.

I don’t think "would we add this feature now if it wasn't already there?” is sufficient anymore, if it ever was. The global Swift code base is growing day by day and each time you remove a feature, you piss somebody off. If the perception of the Swift community is that we keep taking their toys away, it will impede the growth in Swift’s popularity.

The value of variadic functions is imho less than the possibility to omit "()" in procedure calls, and afair, there have been several posts that illustrate the complications of this feature.

I don’t think “it’s a bit complicated” is necessarily good justification for removing a feature.

···

On 20 Apr 2016, at 15:56, Tino Heth <2th@gmx.de> wrote:

I think we are already past that stage, whether we like it or not. There is already quite a lot of Swift code in “production” and some people in the wider community are already resenting some of the removals.

···

On 20 Apr 2016, at 19:24, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Wed Apr 20 2016, Tino Heth <swift-evolution@swift.org> wrote:

Increment/decrement operators, currying, tuple splat and even the
C-style for loop have already been deprecated, and although I would
have preferred to keep some of those constructs, I think it is good
how progressive Swift is pushed forward ("would we add this feature
now if it wasn't already there?").

We're in a stage of Swift's development where we can ask this question
fairly freely,

let myArray = Array([1, 2, 3, 4])

Is that an array with a single element that is an array, or is that a flat array with 4 numbers in it? There is no ambiguity here today - it’s an array with an array inside of it. How do you resolve this sort of situation after removing variadics?

For the record, I’m very -1 for removing variadic but very +1 for a way to inject the contents of an array into a variadic function when calling it.

l8r
Sean

···

On Apr 19, 2016, at 3:06 PM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

On 19 Apr 2016, at 20:25, Justin Jia <justin.jia.developer@gmail.com> wrote:

Cons of removing variadic functions:
1. More verbose syntax.
2. Break old code.

The verbosity is only two characters (square brackets), and it needn’t break old code:

  Before: func myFunc(values:Foo…)
  After: func myFunc(values:[Foo])

  Before: myFunc(foo, bar, baz)
  After: myFunc([foo, bar, baz])

Currently variadic functions just produce an array of arguments anyway, so simply translating call-sites to pass in an array guarantees compatibility.

On Apr 19, 2016, at 10:54 AM, Haravikk <swift-evolution@haravikk.me> wrote:

On 19 Apr 2016, at 17:51, Vladimir.S <svabox@gmail.com> wrote:

I.e. the question is *if we want/need to be able to pass array to existed variadic function*. Not about removing the variadic feature("removing" is offtop for this poposal, as I understand)

I’d say it’s on-topic, as removing variadic functions would eliminate the problem entirely, so if it is considered a better alternative then there would be no need to have an additional means of calling them with an array of arguments.

Personally the way I see it comes down to variadic functions is this:

Pros:
  • Slightly cleaner syntax at call-site.
  • Possibly optimisations unavailable to Array passing?

Cons:
  • Doesn’t do anything that passing an array directly can’t.
  • Passing an array is actually slightly more flexible (can dynamically pass more or less arguments as required at the call site).
  • Less explicit type at call site; gives the appearance of passing instance(s) of Foo, rather than one instance of [Foo], can lead to ambiguity with overloaded functions.
  • Extra syntax to support (enabling array passing would be more code required to support this feature)

I’d also argue that variadic functions increase the learning curve, as the first time you’re presented with one it isn’t necessarily clear what it does unless you’ve encountered them before. Like I say it can be ambiguous at the call-site in particular, as it doesn’t show that an array of [Foo] is being passed as opposed to N instances of Foo (however many are in the call).

While I’ve used them in the past, I’ve never really felt that they simplify anything enough to justify them, as it’s just two square brackets extra to pass an array; this is extra noise sure, but clarifies what is actually happening.

So if variadic functions don’t have any other advantages, then it’s really just a very minor piece of syntactic sugar that can lead to more confusion, less explicit types in function calls, an extra piece of syntax to parse and handle and possibly other features required to support it better (like the one being inquired about). The only other argument I can think of for them is that many other languages have them, but that’s not important to me vs cutting out cruft.

Short version; removing variadic functions would solve the problem of defining overloads for both variadic and array types by only ever requiring the latter.

P.S- I’d also like to note that where possible people should be accepting Sequences or Collections in their methods anyway rather than arrays specifically, as it’s more flexible that way :wink:

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

Heh.. actually there IS ambiguity today because that uses the SequenceType initializer and not the ArrayLiteralConvertible initializer.. so… hmm. :stuck_out_tongue:

Okay so maybe that was a terrible example. Still -1 for removing variadic. :stuck_out_tongue:

l8r
Sean

···

On Apr 19, 2016, at 3:21 PM, Sean Heber <sean@fifthace.com> wrote:

let myArray = Array([1, 2, 3, 4])

Is that an array with a single element that is an array, or is that a flat array with 4 numbers in it? There is no ambiguity here today - it’s an array with an array inside of it. How do you resolve this sort of situation after removing variadics?

For the record, I’m very -1 for removing variadic but very +1 for a way to inject the contents of an array into a variadic function when calling it.

l8r
Sean

On Apr 19, 2016, at 3:06 PM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

On 19 Apr 2016, at 20:25, Justin Jia <justin.jia.developer@gmail.com> wrote:

Cons of removing variadic functions:
1. More verbose syntax.
2. Break old code.

The verbosity is only two characters (square brackets), and it needn’t break old code:

  Before: func myFunc(values:Foo…)
  After: func myFunc(values:[Foo])

  Before: myFunc(foo, bar, baz)
  After: myFunc([foo, bar, baz])

Currently variadic functions just produce an array of arguments anyway, so simply translating call-sites to pass in an array guarantees compatibility.

On Apr 19, 2016, at 10:54 AM, Haravikk <swift-evolution@haravikk.me> wrote:

On 19 Apr 2016, at 17:51, Vladimir.S <svabox@gmail.com> wrote:

I.e. the question is *if we want/need to be able to pass array to existed variadic function*. Not about removing the variadic feature("removing" is offtop for this poposal, as I understand)

I’d say it’s on-topic, as removing variadic functions would eliminate the problem entirely, so if it is considered a better alternative then there would be no need to have an additional means of calling them with an array of arguments.

Personally the way I see it comes down to variadic functions is this:

Pros:
  • Slightly cleaner syntax at call-site.
  • Possibly optimisations unavailable to Array passing?

Cons:
  • Doesn’t do anything that passing an array directly can’t.
  • Passing an array is actually slightly more flexible (can dynamically pass more or less arguments as required at the call site).
  • Less explicit type at call site; gives the appearance of passing instance(s) of Foo, rather than one instance of [Foo], can lead to ambiguity with overloaded functions.
  • Extra syntax to support (enabling array passing would be more code required to support this feature)

I’d also argue that variadic functions increase the learning curve, as the first time you’re presented with one it isn’t necessarily clear what it does unless you’ve encountered them before. Like I say it can be ambiguous at the call-site in particular, as it doesn’t show that an array of [Foo] is being passed as opposed to N instances of Foo (however many are in the call).

While I’ve used them in the past, I’ve never really felt that they simplify anything enough to justify them, as it’s just two square brackets extra to pass an array; this is extra noise sure, but clarifies what is actually happening.

So if variadic functions don’t have any other advantages, then it’s really just a very minor piece of syntactic sugar that can lead to more confusion, less explicit types in function calls, an extra piece of syntax to parse and handle and possibly other features required to support it better (like the one being inquired about). The only other argument I can think of for them is that many other languages have them, but that’s not important to me vs cutting out cruft.

Short version; removing variadic functions would solve the problem of defining overloads for both variadic and array types by only ever requiring the latter.

P.S- I’d also like to note that where possible people should be accepting Sequences or Collections in their methods anyway rather than arrays specifically, as it’s more flexible that way :wink:

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

Pros:
  • Slightly cleaner syntax at call-site.
  • Possibly optimisations unavailable to Array passing?

• Makes calling C and Objective-C functions with variadic parameters less confusing
• Will not break existing Swift code that uses variadic parameters

In both cases you just have to add square brackets to make it an array instead, which doesn’t seem more confusing to me since that’s actually what you’re doing anyway.

• Makes generalising some functions cleaner e.g. zip(a, b) could be generalised to any number of parameters as already mentioned, but if you instead used an array, we would end up with a massive thread about whether the original two parameter zip should be removed

Only if the two-parameter form isn’t implemented any differently; however, being that it’s much simpler case it should be, so there’s a good reason to keep it. Plus with no variadic form masquerading as the same thing there’d be no ambiguity, i.e- it’s clear that they may be implemented differently rather than variadic masquerading as fixed. This comes back to it being clearer at the call-site that an array is being passed, which currently isn’t the case.

My quick an uscientific survey of questions and answers relating to variadic parameters on StackOverflow yields no instances of people asking what does the`…` in `func foo(a: Int…)` do which suggests that the learning curve is actually fairly trivial. However their is a megaton of questions asking things like “why can’t I pass an array" and "how do I forward variadic arguments to another variadic function”.

The ellipsis syntax is straightforward enough, but I think the problem lies more with variadics that overload similar function signatures (like the zip() method) where it becomes less clear what you’re calling, and what’s happening in that call (even if the actual method is pretty much the same). Passing arguments on also couldn’t be simpler in the array form, as you simply pass the array into another function that can take one.

···

On 20 Apr 2016, at 11:44, Jeremy Pereira <jeremy.j.pereira@googlemail.com> wrote:

  * Possibly optimisations unavailable to Array passing?

Indeed, it should be possible to implement varargs by allocating the
argument array on the stack (and having the compiler implicitly copy it to
the heap inside the callee if it escapes). Although you can imagine this
type of optimization being performed for arbitrary arrays, it would be more
difficult and less predictable.

But what about situations when we need to pass an array to function that accepts only variadic params? Don't we need some #splat() function?

···

On 20.04.2016 23:27, Slava Pestov wrote:

On Apr 19, 2016, at 10:54 AM, Haravikk via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Slava

*Cons*:

  * Doesn’t do anything that passing an array directly can’t.
  * Passing an array is actually slightly more flexible (can dynamically
    pass more or less arguments as required at the call site).
  * Less explicit type at call site; gives the appearance of passing
    instance(s) of Foo, rather than one instance of [Foo], can lead to
    ambiguity with overloaded functions.
  * Extra syntax to support (enabling array passing would be more code
    required to support this feature)

I’d also argue that variadic functions increase the learning curve, as
the first time you’re presented with one it isn’t necessarily clear what
it does unless you’ve encountered them before. Like I say it can be
ambiguous at the call-site in particular, as it doesn’t show that an
array of [Foo] is being passed as opposed to N instances of Foo (however
many are in the call).

While I’ve used them in the past, I’ve never really felt that they
simplify anything enough to justify them, as it’s just two square
brackets extra to pass an array; this is extra noise sure, but clarifies
what is actually happening.

So if variadic functions don’t have any other advantages, then it’s
really just a very minor piece of syntactic sugar that can lead to more
confusion, less explicit types in function calls, an extra piece of
syntax to parse and handle and possibly other features required to
support it better (like the one being inquired about). The only other
argument I can think of for them is that many other languages have them,
but that’s not important to me vs cutting out cruft.

Short version; removing variadic functions would solve the problem of
defining overloads for both variadic and array types by only ever
requiring the latter.

P.S- I’d also like to note that where possible people should be accepting
Sequences or Collections in their methods anyway rather than arrays
specifically, as it’s more flexible that way :wink:
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

That may be so, but we are explicitly giving ourselves license to ask
these kinds of questions now because we expect it to become much harder
in the future.

···

on Thu Apr 21 2016, Jeremy Pereira <swift-evolution@swift.org> wrote:

On 20 Apr 2016, at 19:24, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Wed Apr 20 2016, Tino Heth <swift-evolution@swift.org> wrote:

Increment/decrement operators, currying, tuple splat and even the
C-style for loop have already been deprecated, and although I would
have preferred to keep some of those constructs, I think it is good
how progressive Swift is pushed forward ("would we add this feature
now if it wasn't already there?").

We're in a stage of Swift's development where we can ask this question
fairly freely,

I think we are already past that stage, whether we like it or
not. There is already quite a lot of Swift code in “production” and
some people in the wider community are already resenting some of the
removals.

--
Dave

Is there some way that (Type...) as an argument could become to mean ‘Any Collection of type’? A short hand for generic C : CollectionType where C.Generator.Element == Type.
// Function accepting any collection of Int func sum(numbers: Int...) { numbers.reduce(0, combine: +) // Accepts all of the following: func(5, 6, 7) func([5, 6, 7]) func(1...100) func(1...100.lazy.filter{ $0 % 2 == 0 })
It’s just a shame that generic collections are so handy, but a pain to write, whereas parameters of array just need [Type]. Not sure if this could be grafted on top, but just a thought. Possibly any sequence would be even better.
(The only situation it would be disabled is for a type of Any)

Patrick

The question is whether the downside to variadic parameters is really enough to justify _removing_ an existing language feature.

The burden of justification should be on those people wanting to change the language, not on those wanting to maintain the status quo and “I don’t like it” or “I think it makes code a tiny bit less readable” is not sufficient justification, in my opinion because you already have the option not to use the feature.

Afaics, this isn't true:
Increment/decrement operators, currying, tuple splat and even the C-style for loop have already been deprecated, and although I would have preferred to keep some of those constructs, I think it is good how progressive Swift is pushed forward ("would we add this feature now if it wasn't already there?”).

How do these examples show that the burden of justification should not be on those people making the change? I have not claimed that language features should never be removed, only that removal needs some sort of real justification.

I don’t think "would we add this feature now if it wasn't already there?” is sufficient anymore, if it ever was. The global Swift code base is growing day by day and each time you remove a feature, you piss somebody off. If the perception of the Swift community is that we keep taking their toys away, it will impede the growth in Swift’s popularity.

The value of variadic functions is imho less than the possibility to omit "()" in procedure calls, and afair, there have been several posts that illustrate the complications of this feature.

I don’t think “it’s a bit complicated” is necessarily good justification for removing a feature.

···

On Thu, Apr 21, 2016 at 6:12 AM -0700, "Jeremy Pereira via swift-evolution" <swift-evolution@swift.org> wrote:

On 20 Apr 2016, at 15:56, Tino Heth <2th@gmx.de> wrote:

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

Pros:
  • Slightly cleaner syntax at call-site.
  • Possibly optimisations unavailable to Array passing?

• Makes calling C and Objective-C functions with variadic parameters less confusing
• Will not break existing Swift code that uses variadic parameters

In both cases you just have to add square brackets to make it an array instead, which doesn’t seem more confusing to me since that’s actually what you’re doing anyway.

But you still have to do it and a call to (say) printf would look different to its C declaration. Each individual change may not be onerous but you advocating something that will cause an annoyance to a lot of people for a highly subjective gain.

• Makes generalising some functions cleaner e.g. zip(a, b) could be generalised to any number of parameters as already mentioned, but if you instead used an array, we would end up with a massive thread about whether the original two parameter zip should be removed

Only if the two-parameter form isn’t implemented any differently;

Why would it be implemented differently?

My quick an uscientific survey of questions and answers relating to variadic parameters on StackOverflow yields no instances of people asking what does the`…` in `func foo(a: Int…)` do which suggests that the learning curve is actually fairly trivial. However their is a megaton of questions asking things like “why can’t I pass an array" and "how do I forward variadic arguments to another variadic function”.

The ellipsis syntax is straightforward enough, but I think the problem lies more with variadics that overload similar function signatures (like the zip() method) where it becomes less clear what you’re calling, and what’s happening in that call (even if the actual method is pretty much the same). Passing arguments on also couldn’t be simpler in the array form, as you simply pass the array into another function that can take one.

I’m not against the idea of an addition to the language that would create a mechanism to allow passing arrays to variadic functions. I’m simply against the idea of removing the existing feature. As far as I can see, the only arguments put forward are “it might be confusing” and “I don’t like it". I think the bar should be higher than that

···

On 20 Apr 2016, at 13:10, Haravikk <swift-evolution@haravikk.me> wrote:

On 20 Apr 2016, at 11:44, Jeremy Pereira <jeremy.j.pereira@googlemail.com> wrote:

Why can't a simple operator be introduced that unpacks an iterable into separate arguments? Consider this example from Python, which uses the * to unpack iterables:

items = ['a', 'b', 'c']
print(*items) 
# which is equivalent to:
print(items[0], items[1], items[2])

Of course it doesn't have to be an *. It could be any character. The responsibility is still on the programmer to ensure that the function/expression can handle all of the arguments passed into it.

2 Likes

Hi Peter,

Welcome to the Swift community. This thread is four years old, so please avoid resurrecting it as many participants will have moved on but will be emailed, and new participants will not see this thread. Thanks!

1 Like