Update: Conditional conformance has been implemented in Swift 4.1. In particular:
The standard library types Optional, Array, and Dictionary now conform to the Equatable protocol when their element types conform to Equatable. …
(from the Swift CHANGELOG).
Arbitrarily nested arrays of Equatable
elements are Equatable
now
and can be compared with ==
. Your code
var x: [[Simple]] = [[Simple(message: "a")], [Simple(message: "b")]]
var y: [[Simple]] = [[Simple(message: "a")], [Simple(message: "b")]]
x == y
compiles in Xcode 9.3 if Simple
is Equatable
.
(Old answer:)
The reason is similar as in Why is Equatable not defined for optional arrays. Arrays can be compared with ==
if the element type is Equatable
:
/// Returns true if these arrays contain the same elements.
public func ==<Element : Equatable>(lhs: [Element], rhs: [Element]) -> Bool
That’s why
var a: [Simple] = [Simple(message: "a")]
var b: [Simple] = [Simple(message: "a")]
a == b // -> true
compiles.
But even for equatable types T
, Array<T>
does not conform to the Equatable
protocol, compare Why can’t I make Array conform to Equatable?. Therefore, in
var x: [[Simple]] = [[Simple(message: "a")], [Simple(message: "b")]]
var y: [[Simple]] = [[Simple(message: "a")], [Simple(message: "b")]]
x == y // -> ERROR! Binary operator '==' cannot be applied to two '[[Simple]]’ operands
x
and y
are arrays with the element type [Simple]
which does
not conform to the Equatable
protocol, and there is no
matching ==
operator.
You could define a generic ==
operator for simply nested arrays as
func ==<Element : Equatable> (lhs: [[Element]], rhs: [[Element]]) -> Bool {
return lhs.count == rhs.count && !zip(lhs, rhs).contains {$0 != $1 }
}
or more simply (as suggested by @kennytm):
func ==<Element : Equatable> (lhs: [[Element]], rhs: [[Element]]) -> Bool {
return lhs.elementsEqual(rhs, by: ==)
}
This makes x == y
compile and work as expected. At present, there seems
to be no way to define a ==
operator on arbitrarily nested arrays.