> 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

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

Reply via email to