[swift-users] Generic factory method and type inference
Brent Royal-Gordon
brent at architechies.com
Thu Mar 17 10:51:49 CDT 2016
> final class Something<T> {
>
> let value: T
>
> init(initial: T) {
> value = initial
> }
>
> }
>
> extension Something {
>
> class func zip<A, B>(a: A, _ b: B) -> Something<(A, B)> {
> let initial = (a, b)
> return Something<(A, B)>(initial: initial)
> }
>
> }
>
> How come I can’t call zip without explicitly specifying return type?
>
> // ERROR: Cannot invoke `zip` with an argument list of type `(Int, Int)`
> let y = Something.zip(1, 2)
>
> // OK: Works but it’s unacceptable to require this on caller's side
> let x = Something<(Int, Int)>.zip(1, 2)
The reason you're seeing this is that there's nothing in this call:
let y = Something.zip(1, 2)
That tells Swift what `T` should be. The return type of the `zip` method is not connected to T; you can actually put any random type in the angle brackets after Something:
let y = Something<UICollectionViewDelegateFlowLayout>.zip(1, 2)
Unfortunately, Swift doesn't currently have the features needed to properly connect `T` to the return type. If the language were more sophisticated, you could say something like this:
extension<A, B> Something where T == (A, B) {
class func zip(a: A, _ b: B) -> Something {
let initial = (a, b)
return Something(initial: initial)
}
}
But for now, you'll have to make do with this horrible hack, which works by meaninglessly reusing the T type parameter:
extension Something {
class func zip<B>(a: T, _ b: B) -> Something<(T, B)> {
let initial = (a, b)
return Something<(T, B)>(initial: initial)
}
}
Hope this helps,
--
Brent Royal-Gordon
Architechies
More information about the swift-users
mailing list