问题
In Swift 2.1, following code can be compiled.
let a = [1: [1]]
a == [1: [1]]
However, following code cannot be compiled.
let a = [1: [1]]
let b = [1: [1]]
a == b // => binary operator '==' cannot be applied to two '[Int : Array<Int>]' operands
How understand this behavior?
回答1:
There is a ==
operator comparing two Swift dictionaries, however it
requires that the value type is Equatable
:
public func ==<Key : Equatable, Value : Equatable>(lhs: [Key : Value], rhs: [Key : Value]) -> Bool
The problem is that even for equatable types T
, Array<T>
does not conform to the Equatable
protocol. See for example
Why can't I make Array conform to Equatable? for a discussion
in the Apple developer forum.
That explains why
let a = [1: [1]]
let b = [1: [1]]
a == b // => binary operator '==' cannot be applied to two '[Int : Array<Int>]' operands
does not compile. In your first example
let a = [1: [1]]
a == [1: [1]]
the compiler is so smart to take the literal array [1]
as an
NSArray
literal, using
extension NSArray : ArrayLiteralConvertible {
/// Create an instance initialized with `elements`.
required public convenience init(arrayLiteral elements: AnyObject...)
}
And this compiles because all classes inheriting from
NSObject
conform to Equatable
.
Here is a simpler example demonstrating the same issue:
func foo<T : Equatable>(x : T) {
print(x.dynamicType)
}
let ar = [1, 2, 3]
// This does not compile:
foo(ar) // error: cannot invoke 'foo' with an argument list of type '([Int])'
foo([1, 2, 3]) // Output: __NSArrayI
As one can see, the literal array is converted to some subclass of the
NSArray
class cluster when passed to a function expecting an Equatable
argument.
Note also that if you only import Swift, but not Foundation (or UIKit, ...) then neither
foo([1, 2, 3])
nor your first example compiles.
来源:https://stackoverflow.com/questions/33730653/swift-strange-behavior-with-dictionary