Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what's the meaning of "Collection where Indices.Iterator.Element == Index"

Tags:

swift

I could not figure out the purpose/meaning of "Indices.Iterator.Element == Index" in following code

extension Collection where Indices.Iterator.Element == Index {

    /// Returns the element at the specified index iff it is within bounds, otherwise nil.
    subscript (safe index: Index) -> Generator.Element? {
        return indices.contains(index) ? self[index] : nil
    }
}
like image 644
LiangWang Avatar asked Dec 30 '16 05:12

LiangWang


2 Answers

The generic constraint syntax where T == U says that the type T must be the same type as type U.

Let's do a simpler example first:

protocol GenericProtocol {
    associatedtype T
    associatedtype U
}

extension GenericProtocol where T == U {
    func foo() {}
}

class ConcreteClassA: GenericProtocol {
    typealias T = Int
    typealias U = Float
}

class ConcreteClassB: GenericProtocol {
    typealias T = Int
    typealias U = Int
}

let a = ConcreteClassA()
let b = ConcreteClassB()

Now which of these, a or b has the member foo? The answer is b.

Since the extension's generic constraint says that T and U must be the same type, the extension is only applied to ConcreteClassB because its T and U are both Int.

Back to your code now.

In your code, you're saying that Indices.Iterator.Element must be the same type as Index. Let's figure what these two types are respectively.

Indices is the type of the property indices. So Indices.Iterator.Element is type of each index of the collection. Index on the other hand, is the type of value that you can put into the subscript of of the collection. This constraint seems excessive but it is in fact not. I can't think of an example of a type where the constraint is not true. But you can in theory create such a type. That's why the constraint is there.

If the constraint weren't there, this would not compile:

indices.contains(index)
like image 174
Sweeper Avatar answered Oct 27 '22 07:10

Sweeper


contains(_:) is being called on the indices property (which has type Indices), with the parameter called index (which has type Index). The only way this is possible is if the Indices elements are of the same type as Index.

This constraint is added to assert that this is true, thus allowing the code to compile.

Take Array of example. Its Indices associated type is set to CountableRange<Int> and its Index associated type is set to Int. Array is able to conform to your protocol because it's true that the elements of the iterator of CountableRange<Int> (CountableRange<Int>.Iterator.Element) and the type of Index are both Int.

like image 40
Alexander Avatar answered Oct 27 '22 06:10

Alexander