Re: [swift-users] Workaround for generics not currently supporting conditional conformance to a protocol
> On Nov 16, 2016, at 16:35, Jordan Rosewrote: > > >>> On Nov 16, 2016, at 7:35, David Sweeris via swift-users >>> wrote: >>> >>> >>> On Nov 15, 2016, at 11:55 PM, Howard Lovatt 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 wrote: > On Nov 15, 2016, at 21:39, Howard Lovatt via swift-users > 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 { > 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@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..> 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(_ 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___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
Re: [swift-users] Workaround for generics not currently supporting conditional conformance to a protocol
Pity nothing else works, looks like I am stuck with multiple wrappers. I will echo Dave's, Tim's, and Jordan's thoughts, roll on Conditional Conformance. Thanks for your help. -- Howard. On 17 November 2016 at 09:35, Jordan Rosewrote: > > On Nov 16, 2016, at 7:35, David Sweeris via swift-users < > swift-users@swift.org> wrote: > > > On Nov 15, 2016, at 11:55 PM, Howard Lovatt > 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 wrote: > >> >> > On Nov 15, 2016, at 21:39, Howard Lovatt via swift-users < >> swift-users@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 { >> > 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@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.. 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(_ 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. > > Jordan > ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
[swift-users] Workaround for generics not currently supporting conditional conformance to a protocol
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 { 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@swift.org https://lists.swift.org/mailman/listinfo/swift-users