Well, my concern is that generally, sooner or later, variadics users will start to hit dead ends where they will want to pass a pack expansion that was once inevitably tupled. I hope that this is just a temporary limitation that will be lifted as variadics will mature. At least variadic types future directions suggests that.
Correction: I just realized the above code doesn't work as I thought (though it should achieve the same purpose in most, if not all, cases). The variadic generic bar()
is effectively used as a non-variadic generic function. For example, the following two are equivalent:
func foo<each T: CustomStringConvertible>(_ value: repeat each T) {
repeat bar(each value)
}
// variadic generic version
func bar<each T: CustomStringConvertible>(_ value: repeat each T) {
repeat print(each value)
}
func foo<each T: CustomStringConvertible>(_ value: repeat each T) {
repeat bar(each value)
}
// generic version
func bar<T: CustomStringConvertible>(_ value: T) {
print(value)
}
I was wrong on this. With SE-0399 it's possibe to reference element in tuple in a general way. Example:
func foo<each T: CustomStringConvertible>(_ value: repeat each T) -> (repeat each T) {
(repeat each value)
}
func bar<T: CustomStringConvertible>(_ value: T) {
print(value)
}
// This saves foo() output in a tuple and passes it to bar()
func test<each T: CustomStringConvertible>(_ value: repeat each T) {
let tuple = (repeat foo(each value))
repeat bar(each tuple)
}
Using this approach, I think the following is what you were looking for. Note the second foo()
call in test()
is generic function in disguise.
protocol P {}
struct A: P {}
struct B: P {}
func foo<each T>(_ value: repeat each T) -> (repeat each T) where repeat each T: P {
(repeat each value)
}
func test<each T>(_ value: repeat each T) -> (repeat each T) where repeat each T: P {
let tuple = (repeat foo(each value))
return (repeat foo(each tuple))
}
test(A(), B())