Equatable with two two-dimension array

In Pure Swift environment (no briding to NSArray)

Problem:


[[1]]==[[1]] //false


or


([[1]] as Array)==([[1]] as Array) //false



This problem only happens in pure Swift environment.

Though [1] == [1], any array of integers is not marked equatable. Programmer cannot mark [Int], [String], …, etc. as Equatable protocol.

Thus two [[Int]] cannot be compared using “==“.


Solution 1:


extension SequenceType: Equatable where Generator.Element: Equatable {


}

This gramma should be allowed in newer version of Swift.

This means a SequenceType with Equatable elements can be marked Equatable.


Solution 2:

You can make a new mechanism in Swift that automatically binds “Equatable” to any generic type has “==“ operator defined.

For example, in Swift Standard Swift Library, you have defined

==<T: Equatable>(lhs:[T], rhs:[T])->Bool

Thus, the special generic type [T] where T:Equatable

should be automatically marked as “Equatable".

TLTR: I am a bit surprised by this too. One might wonder if this is intentional or not.


Just providing some more details here:


In order to see why eg this:

// NOTE: No "import Cocoa" or "import Foundation" or anything.
let a = [123] == [123]
let b = [[123]] == [[123]]
print(a) // Prints true
print(b) // Prints false (why not true?)

won't work the way we might expect, we can cmd-click on the second == which will take us to the std lib definition of that ==, which reads:

func ==<T>(lhs: UnsafePointer<T>, rhs: UnsafePointer<T>) -> Bool


Ok ... so that is the best match it can find, since those are array(literal)s which might be given as args to functions taking UnsafePointers, and this is according to the rules of Swift. (Cmd-clicking on the first == will take us to the less surprising function/operator cited by the OP.)


Now let's do this:

import Foundation // <-- NOTE
let a = [123] == [123]
let b = [[123]] == [[123]]
print(a) // true
print(b) // true

and cmd-click that second == again. We'll be taken to the generated header for the ObjectiveC module and see this:

func ==(lhs: NSObject, rhs: NSObject) -> Bool


Ok ...


As you say, this "situation" would be "solved" if all Array<T: Equatable> types were conforming to Equatable. But at least in Xcode 7 beta 2 (Swift 2 beta), that doesn't seem possible. I happened to ask a question about exactly this some days ago, here:

https://forums.developer.apple.com/message/16869


Here's an alternative solution / very ugly hack for the [[...]] and [[[...]]] special cases, if anyone should be interested:

// NOTE: Will work with or without import Foundation, ObjectiveC-module's == will be used rather than these if Foundation is imported.
func ==<T : Equatable>(lhs: [[T]], rhs: [[T]]) -> Bool {
    guard lhs.count == rhs.count else { return false }
    for i in lhs.indices { if rhs[i] != lhs[i] { return false } }
    return true
}
func !=<T : Equatable>(lhs: [[T]], rhs: [[T]]) -> Bool { return !(lhs == rhs) }
func ==<T : Equatable>(lhs: [[[T]]], rhs: [[[T]]]) -> Bool {
    guard lhs.count == rhs.count else { return false }
    for i in lhs.indices { if rhs[i] != lhs[i] { return false } }
    return true
}
func !=<T : Equatable>(lhs: [[[T]]], rhs: [[[T]]]) -> Bool { return !(lhs == rhs) }

let a = [123] == [123]
let b = [[123]] == [[123]]
let c = [[[123]]] == [[[123]]]
print(a) // true
print(b) // true
print(c) // true

After I posted my question, I saw yours in the suggestion list. I'm surprising we find the same issue, that is array with equatable elements can not be marked equatable though they can use ==.


You can define as many as possible == for a few dimensions, but this is still limited. if you defiend == for two dimensions, what about three? If you defined == for three dimension, what about four?


I tried many ways to solve this problem, but none of them can easily solve this problem, unless developer defined a new structure conform to SequenceType or ArrayType, maybe called EquatableArray<T: Equatable>.

Equatable with two two-dimension array
 
 
Q