Hi there,
I'm playing around with the new Parameter packs in Xcode 15.0 Beta 5 (15A5209g). In iOS 17 we can do this easily:
@available(iOS 17, *)
struct Factory<Service, each Arg> {
let factory: (Any) -> Any
init(factory: @escaping (Any) -> Any) {
self.factory = factory
}
func make(_ arg: repeat each Arg) -> Service? {
factory((repeat each arg)) as? Service
}
}
Unfortunately Parameter packs in generic types are only available in iOS 17. But there's a workaround to get a similar functionality in Swift 5.8:
struct Factory2<Service, Args> {
let factory: (Any) -> Any
init(factory: @escaping (Any) -> Any) {
self.factory = factory
}
func make() -> Service? where Args == Void {
factory(()) as? Service
}
func make(_ arg: Args) -> Service? {
factory(arg) as? Service
}
func make<Arg1, Arg2>(_ arg1: Arg1, _ arg2: Arg2) -> Service? where (Arg1, Arg2) == Args {
factory((arg1, arg2)) as? Service
}
func make<Arg1, Arg2, Arg3>(_ arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3) -> Service? where (Arg1, Arg2, Arg3) == Args {
factory((arg1, arg2, arg3)) as? Service
}
}
Now I can pass the argument types as a tuple: Factory2<MyService, (String, Int, Float)>
and the make functions I've generated now will allow for this syntax:
factory.make("a", 1, 5.0)
instead of:
factory.make(("a", 1, 5.0))
so I don't have to pass the tuple as the argument. Obviously this only works up to 3 arguments.
So I thought maybe if I use constraint on the struct generic I could get the same functionality with unlimited number of arguments:
struct Factory3<Service, Args> {
let factory: (Any) -> Any
init(factory: @escaping (Any) -> Any) {
self.factory = factory
}
func make<each Arg>(_ arg: repeat each Arg) -> Service? where (repeat each Arg) == Args {
factory((repeat each arg)) as? Service
}
}
But this code does not compile and it fails with a nonzero exit code. I am wondering if this is just a bug in the beta or I'm pushing the compiler too hard on this.
Any suggestions are welcome.
Thanks!