[swift-users] Workaround for generics not currently supporting conditional conformance to a protocol

David Sweeris davesweeris at mac.com
Wed Nov 16 20:30:40 CST 2016


> On Nov 16, 2016, at 16:35, Jordan Rose <jordan_rose at apple.com> wrote:
> 
> 
>>> On Nov 16, 2016, at 7:35, David Sweeris via swift-users <swift-users at swift.org> wrote:
>>> 
>>> 
>>> On Nov 15, 2016, at 11:55 PM, Howard Lovatt <howard.lovatt at gmail.com> wrote:
>>> 
>>> @Dave,
>>> 
>>> How do I write that though.
>>> 
>>> I can't write:
>>> 
>>>     extension Array: Equatable {
>>>         static func ==(lhs: Array, rhs: Array) -> Bool {
>>>             let size = lhs.count
>>>             precondition(rhs.count == size, "The arrays must be the same length")
>>>             for i in 0 ..< size {
>>>                 if (lhs[i] as! Equatable) != (rhs[i] as! Equatable) {
>>>                     return false
>>>                 }
>>>             }
>>>             return true
>>>         }
>>>     }
>>> 
>>> Because I can't cast to an Equatable, because Equatable uses Self.
>>> 
>>> Am I missing something?
>>> 
>>>  -- Howard.
>>> 
>>>   -- Howard.
>>> 
>>>> On 16 November 2016 at 16:35, David Sweeris <davesweeris at mac.com> wrote:
>>>> 
>>>> > On Nov 15, 2016, at 21:39, Howard Lovatt via swift-users <swift-users at swift.org> wrote:
>>>> >
>>>> > Hi All,
>>>> >
>>>> > Does anyone have a good workaround for generics not currently supporting conditional conformance to a protocol. As stated in the Generics Manifesto something like this would be nice:
>>>> >
>>>> >   extension Array: Equatable where Element: Equatable {
>>>> >         static func ==(lhs: Array, rhs: Array) -> Bool { ... }
>>>> >     }
>>>> >
>>>> > But I would currently write a wrapper, something like:
>>>> >
>>>> >     struct ArrayE<T: Equatable> {
>>>> >         var elements: [T]
>>>> >     }
>>>> >     extension ArrayE: Equatable {
>>>> >         static func ==(lhs: ArrayE, rhs: ArrayE) -> Bool { ...  }
>>>> >     }
>>>> >
>>>> > This can get unwieldy when there are a lot of conditional protocol extensions required, i.e. wrappers round wrappers.
>>>> >
>>>> > Is there a better way?
>>>> >
>>>> > Thanks for any tips,
>>>> >
>>>> >   -- Howard.
>>>> > _______________________________________________
>>>> > swift-users mailing list
>>>> > swift-users at swift.org
>>>> > https://lists.swift.org/mailman/listinfo/swift-users
>>>> 
>>>> Can you make Array conform to Equatable for any T and then in the == function, if T conforms to Equatable loop the Arrays to check if they're equal, and if it doesn't conform just return false?
>>>> 
>>>> I mean, it's still "wrong", but at least you won't get any false positives.
>>>> 
>>>> - Dave Sweeris
>>> 
>> 
>> You are correct. The work-around is to use two extensions and overload the == operator:
>> 
>> extension Array: Equatable {
>>     public static func == (lhs: Array, rhs: Array) -> Bool {
>>         return false
>>     }
>> }
>> extension Array where Element : Equatable {
>>     public static func == (lhs: Array, rhs: Array) -> Bool {
>>         return lhs.count == rhs.count && {
>>             for i in 0..<lhs.count {
>>                 if lhs[i] != rhs[i] {
>>                     return false
>>                 }
>>             }
>>             return true
>>         }()
>>     }
>> }
>> 
>> It works in playgrounds (Xcode 8.1 (8B62)), but I haven’t tested it outside a few trivial cases.
> 
> This does not work. The == dispatch for Arrays is static in this case, not dynamic. You can test this by writing something generic on Equatable.
> 
> func same<T: Equatable>(_ x: T, _ y: T) -> Bool { return x == y }
> print(same([1], [2]))
> 
> Rule of thumb: overloads are resolved statically, protocol requirements are invoked dynamically. You cannot get dynamic behavior out of just overloads, ever.
> 
> I don't think there's a way to get this behavior today, unfortunately.

Aw, nuts! I forgot to try adding another level of, um... genericititty?

Yeah, I think you're right... On the plus side, when conditional conformance hits the wrapper structs can be backed out just by searching your project for their name and replacing it with "Array" (or "Set", etc), right?

- Dave Sweeris
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20161116/16927a30/attachment.html>


More information about the swift-users mailing list