Невозможно использовать 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
    }
}
Другие вопросы по тегам