matm
matm

Reputation: 7079

What does [[Element].Element] mean in Swift's == operator overload?

Swift's Array type implements Equatable protocol in a way that == and != operators are overloaded:

extension Array : Equatable where Element : Equatable {

    /// - Parameters:
    ///   - lhs: An array to compare.
    ///   - rhs: Another array to compare.
    public static func == (lhs: [[Element].Element], rhs: [[Element].Element]) -> Bool

    public static func != (lhs: [[Element].Element], rhs: [[Element].Element]) -> Bool
}

I've got three questions:

  1. What is [[Element].Element]?
  2. How to read that?
  3. Why I cannot use that construct in my Swift code?

So far my reasoning is:

  1. [Element] is a type definition, i.e. an array of types denoted by Element (Element is a placeholder type name).
  2. Based on 1, next I reckon outermost brackets denote another array, BUT...
  3. I can't figure out what [Element].Element means as .Element is puzzling for me.

Upvotes: 4

Views: 203

Answers (1)

Martin R
Martin R

Reputation: 539805

Generally, TypeA.TypeB can denote a nested type or type alias TypeB inside TypeA, or an associated type TypeB of a protocol TypeA.

Array conforms to Sequence, and that has an associatedtype Element for the type of the elements returned from its iterator. For arrays that is equal to the array's element type. So for any type T:

Array<T>.Element == T

and consequently,

[Array<T>.Element] == [T]

Example:

print(type(of: [Array<Int>.Element].self))
// Array<Int>.Type

However, using the bracket notation for the inner array is not accepted by the compiler:

print(type(of: [[Int].Element].self))
// Expected member name or constructor call after type name

Now back to your question: The actual definition of that == operator is

extension Array : Equatable where Element : Equatable {
    public static func ==(lhs: Array<Element>, rhs: Array<Element>) -> Bool {
        // ...
    }
}

The “generated interface” is, as you noticed:

extension Array : Equatable where Element : Equatable {
    public static func == (lhs: [[Element].Element], rhs: [[Element].Element]) -> Bool
}

So apparently, the “interface generator” interprets the Element in lhs: Array<Element> not as the placeholder type, but as the associated Element type of the Sequence protocol, i.e. the types of the operands are

Array<Array<Element>.Element>

which – as shown above – is just [Element]. But then the interface is emitted using the bracket notation

[[Element].Element]

which should be the same, but is not accepted by the compiler.

Upvotes: 2

Related Questions