Невозможно использовать indices.contains() в расширении Collection в Swift 3
Я написал следующее расширение в 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
}
}
Однако оказывается, что Swift 3.0 не имеет contains()
функция. Вместо этого он предлагает мне следующий синтаксис для этого метода:
indices.contains(where: { (<#Self.Indices.Iterator.Element#>) -> Bool in
<# code ??? what should it do??? #>
})
Проблема в том, что я не знаю, что он должен содержать внутри блока. Любая помощь с переносом, пожалуйста?
1 ответ
Swift 4 Обновление
В Swift 4 благодаря возможности иметь where
оговорки о связанных типах, Collection
теперь обеспечивает, что Indices
"s Element
тип того же типа, что и Collection
"s Index
,
Следовательно, это означает, что мы можем просто сказать:
extension Collection {
/// Returns the element at the specified index iff it is within bounds, otherwise nil.
subscript (safe index: Index) -> Element? {
return indices.contains(index) ? self[index] : nil
}
}
Свифт 3
Sequence
Протокол в Swift 3 по-прежнему имеет contains(_:)
метод, который принимает элемент последовательности, если последовательность имеет Equatable
элементы:
extension Sequence where Iterator.Element : Equatable {
// ...
public func contains(_ element: Self.Iterator.Element) -> Bool
// ...
}
Проблема, с которой вы сталкиваетесь, связана с изменением типа Collection
"s indices
требование к собственности. В Swift 2 это было типа Range<Self.Index>
- однако в Swift 3 он имеет тип Indices
(связанный тип Collection
протокол):
/// A type that can represent the indices that are valid for subscripting the
/// collection, in ascending order.
associatedtype Indices : IndexableBase, Sequence = DefaultIndices<Self>
Поскольку в настоящее время в Свифте нет возможности для Collection
сам протокол , чтобы выразить это Indices
"s Iterator.Element
имеет тип Index
( однако это будет возможно в будущей версии Swift), компилятор не сможет узнать, что вы можете передать что-то типа Index
в contains(_:)
, Это потому, что в настоящее время вполне возможно, чтобы тип соответствовал Collection
и реализовать Indices
с любым типом элемента, который он хочет.
Поэтому решение состоит в том, чтобы просто ограничить ваше расширение, чтобы гарантировать, что Indices
имеет элементы типа Index
, позволяя вам пройти index
в contains(_:)
:
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) -> Iterator.Element? {
return indices.contains(index) ? self[index] : nil
}
}