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
}
}
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)
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With