I wrote following extension in Swift 2.3:
extension CollectionType {
/// 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
}
}
However, it turns out that Swift 3.0 does not have contains()
function. Instead, it offers me following syntax for this method:
indices.contains(where: { (<#Self.Indices.Iterator.Element#>) -> Bool in
<# code ??? what should it do??? #>
})
The problem is that I don't know what should it contain inside the block. Any help with migrating it, please?
Swift 4 Update
In Swift 4, thanks to the ability to have
where
clauses on associated types,Collection
now enforces thatIndices
'sElement
type is the same type as theCollection
'sIndex
.This therefore means that we can just say:
Swift 3
The
Sequence
protocol in Swift 3 still has acontains(_:)
method, which accepts an element of the sequence if the sequence is ofEquatable
elements:The problem you're encountering is due to the change in the type of
Collection
'sindices
property requirement. In Swift 2, it was of typeRange<Self.Index>
– however in Swift 3, it is of typeIndices
(an associated type of theCollection
protocol):As there's currently no way in Swift for the
Collection
protocol itself to express thatIndices
'sIterator.Element
is of typeIndex
(this will however be possible in a future version of Swift), there's no way for the compiler to know that you can pass something of typeIndex
intocontains(_:)
. This is because it's currently fully possible for a type to conform toCollection
and implementIndices
with whatever element type it wants.Therefore the solution is to simply constrain your extension to ensure that
Indices
does have elements of typeIndex
, allowing you to passindex
intocontains(_:)
: