Posted a new proposal, feedback appreciated:

https://github.com/Haravikk/swift-evolution/blob/2743411af02e3ac6761fbdd780ede1af4cc34ee7/proposals/0000-variadics-as-attribute.md

One talking point raised already is the correct location for the attribute 
(parameter or type); I'm undecided personally as there are arguments for both, 
probably not an important detail though (core team can make a decision on that 
I think), since the guidelines on attributes have been debated a few times 
already.

Also, no matter how much I use it I seem to be the worst at using the Github 
website, so apologies for my many mistakes on that side of things ;)

Variadics as Attribute

Proposal: SE-NNNN 
<https://github.com/Haravikk/swift-evolution/blob/2743411af02e3ac6761fbdd780ede1af4cc34ee7/proposals/0000-variadics-as-attribute.md>
Author: Haravikk <https://github.com/haravikk>
Status: Awaiting review
Review manager: TBD
 
<https://github.com/Haravikk/swift-evolution/blob/2743411af02e3ac6761fbdd780ede1af4cc34ee7/proposals/0000-variadics-as-attribute.md#introduction>Introduction

This proposal is for a redesign of the variadic function parameter syntax as an 
attribute for greater flexibility.

 
<https://github.com/Haravikk/swift-evolution/blob/2743411af02e3ac6761fbdd780ede1af4cc34ee7/proposals/0000-variadics-as-attribute.md#motivation>Motivation

Currently Swift variadic functions cannot be called with an array of values, 
potentially requiring two declarations like so:

func someMethod<C:Collection where C.Iterator.Element == Int>(_ values:C) { … } 
// Regular method
func someMethod(_ values:Int...) { someMethod(values) } // Variadic method
In some cases this leads to only one being defined, forcing developers to use 
that particular style. When this is the variadic option this means the method 
is restricted in how it can be used, and parameters constructed.

 
<https://github.com/Haravikk/swift-evolution/blob/2743411af02e3ac6761fbdd780ede1af4cc34ee7/proposals/0000-variadics-as-attribute.md#proposed-solution>Proposed
 solution

This proposal is to replace the current form of variadic declaration syntax 
(trailing elipsis) with a new attribute @variadicthat enables any suitable 
iterable parameter to be called in variadic form if desired.

 
<https://github.com/Haravikk/swift-evolution/blob/2743411af02e3ac6761fbdd780ede1af4cc34ee7/proposals/0000-variadics-as-attribute.md#detailed-design>Detailed
 design

Quite simply, instead of a trailing elipsis, a variadic parameter will instead 
be defined via a new @variadic attribute which can be placed upon any function 
parameter with a type conforming to ArrayLiteralConvertible, or which is a 
generic constraint against IteratorProtocol, Sequence or Collection such that a 
default (such as Array) can be used to fulfil the variadic call. Otherwise 
variadic parameters can be specified with the same restrictions they have now 
(must not be ambiguous).

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
This altered declaration syntax has a number of advantages over existing 
variadics:

No requirement for a custom syntax (see alternatives however)
A single declaration can handle variadic and collection/sequence/iterator 
invocation (no need for some other workaround such as reflection).
Greater flexibility over the actual type of the variadic 
collection/sequence/iterator, not restricted to Array or array-like.
Developers are free to choose the syntax used at the call-site based upon 
preference (or pass a variable instead).
Declaration is more discoverable (option-click the @variadic attribute to view 
documenation).
 
<https://github.com/Haravikk/swift-evolution/blob/2743411af02e3ac6761fbdd780ede1af4cc34ee7/proposals/0000-variadics-as-attribute.md#impact-on-existing-code>Impact
 on existing code

This proposal as given would remove the existing variadic syntax (trailing 
elipsis), but a fix-it should enable easy conversion between the following:

func someMethod(_ values:Int...) { … } // Old style
func someMethod(@variadic _ values:[Int]) { … } // New style
However there is an alternative to consider below that will affect this.

 
<https://github.com/Haravikk/swift-evolution/blob/2743411af02e3ac6761fbdd780ede1af4cc34ee7/proposals/0000-variadics-as-attribute.md#alternatives-considered>Alternatives
 considered

One alternative is to simply have the existing variadic syntax produce a method 
taking an array of the same type, that is implicitly capable of being used in 
variadic style (but also used directly with Array values). However this has 
less flexibility than the above, which permits non-Array types. A compromise 
could be to allow the existing style to remain as a shorthand, though this may 
discourage consideration of the most appropriate type (in general developers 
should be encouraged to accept generic types for greatest utility wherever 
possible, but if trailing elipsis is easy we may just end up with Array being 
used most often).

The other main alternative considered was removing variadics completely; while 
this is actually the preference of some (myself included), it seems a lot 
developers do not wish this. This proposal is intended as a compromise that 
coallesces variadics with regular functions, without eliminating the 
possibility to use either style at the call site as developers prefer.
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to