This is subtle and I'm not sure how Swift would handle it, since both ways are technically correct.
I have a protocol that implements equality between all instances of the protocol:
public protocol Drawable: Equatable {
var width: Int { get }
var height: Int { get }
subscript(x: Int, y: Int) -> Color { get }
}
public extension Drawable {
static func == (lhs: Self, rhs: Self) -> Bool {
guard lhs.width == rhs.width && lhs.height == rhs.height else { return false }
for x in 0..<lhs.width {
for y in 0..<lhs.width {
guard lhs[x, y] == rhs[x, y] else { return false }
}
}
return true
}
static func == (lhs: Self, rhs: some Drawable) -> Bool {
guard lhs.width == rhs.width && lhs.height == rhs.height else { return false }
for x in 0..<lhs.width {
for y in 0..<lhs.width {
guard lhs[x, y] == .init(rhs[x, y]) else { return false }
}
}
return true
}
}
This is not efficient, but it is a correct way of comparing arbitrary drawables.
When types are known however, comparing individual pixels can be avoided, like for two circles:
public struct Circle: OptimizedDrawable, Hashable {
public var width: Int { radius * 2 + 1 }
public var height: Int { radius * 2 + 1 }
public let color: Color
public let radius: Int
public let fill: Bool
...
}
I'm not sure though since I can't go-to-definition on operators in Xcode: is dedicated equality for two Cricles still derived because it inherits the Equatable requirement from Drawable? Does it just use the inefficient generic equality? If it isn't derived, does adding Equatable
or Hashable
explicitly derive it despite the existing generic implementation, or do I have to implement ==
for each drawable manually?