无法在 Swift 的集合扩展中使用 indices.contains() 3
Unable to use indices.contains() in a Collection extension in 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
}
}
然而,原来Swift3.0没有contains()
功能。相反,它为我提供了此方法的以下语法:
indices.contains(where: { (<#Self.Indices.Iterator.Element#>) -> Bool in
<# code ??? what should it do??? #>
})
问题是我不知道块中应该包含什么。请帮助迁移它?
Swift 4 次更新
在Swift 4中,由于the ability to have where
clauses on associated types, Collection
now enforces that Indices
的Element
类型与Collection
的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
}
}
Swift 3
Swift3中的Sequence
协议还有一个contains(_:)
方法,如果序列是Equatable
个元素,它接受序列的一个元素:
extension Sequence where Iterator.Element : Equatable {
// ...
public func contains(_ element: Self.Iterator.Element) -> Bool
// ...
}
您遇到的问题是由于 Collection
的 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>
因为目前 Swift 中 Collection
协议 本身 无法表达 Indices
的 Iterator.Element
是 Index
(this will however be possible in a future version of 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
}
}
我在 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
}
}
然而,原来Swift3.0没有contains()
功能。相反,它为我提供了此方法的以下语法:
indices.contains(where: { (<#Self.Indices.Iterator.Element#>) -> Bool in
<# code ??? what should it do??? #>
})
问题是我不知道块中应该包含什么。请帮助迁移它?
Swift 4 次更新
在Swift 4中,由于the ability to have where
clauses on associated types, Collection
now enforces that Indices
的Element
类型与Collection
的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
}
}
Swift 3
Swift3中的Sequence
协议还有一个contains(_:)
方法,如果序列是Equatable
个元素,它接受序列的一个元素:
extension Sequence where Iterator.Element : Equatable {
// ...
public func contains(_ element: Self.Iterator.Element) -> Bool
// ...
}
您遇到的问题是由于 Collection
的 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>
因为目前 Swift 中 Collection
协议 本身 无法表达 Indices
的 Iterator.Element
是 Index
(this will however be possible in a future version of 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
}
}