[swift-users] Generic factory method and type inference

Rudolf Adamkovič salutis at me.com
Thu Mar 17 11:52:14 CDT 2016


Thanks for all the information. This was a cross-post from Stack Overflow:

http://stackoverflow.com/questions/36061561/generic-factory-method-and-type-inference <http://stackoverflow.com/questions/36061561/generic-factory-method-and-type-inference>

If you are a Stack Overflow user, you can copy the answer there and I will accept it as correct.

Either way, thanks for the explanation!

R+

> On 17 Mar 2016, at 16:51, Brent Royal-Gordon <brent at architechies.com> wrote:
> 
>> 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
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160317/ad3346f7/attachment.html>


More information about the swift-users mailing list