我正在实现对Swift的CollectionType的扩展,它提供了在集合中查找子序列并查找该子序列范围的功能。我在操场上工作的代码就是:
extension CollectionType where Generator.Element:Equatable, Index:ForwardIndexType, SubSequence.Generator.Element == Generator.Element {
func search<S: CollectionType where S.Generator.Element == Generator.Element, S.Index:ForwardIndexType>(pattern: S) -> Self.Index? {
return self.lazy.indices.indexOf{
self[$0..<self.endIndex].startsWith(pattern)
}
}
func rangeOf<S: CollectionType where S.Generator.Element == Generator.Element, S.Index:ForwardIndexType, Index:ForwardIndexType>(pattern: S) -> Range<Index>? {
if let start = self.search(pattern) {
var end = start
for _ in pattern.startIndex..<pattern.endIndex {
end = end.advancedBy(1)
}
return start..<end
} else {
return nil
}
}
}
简单的游乐场测试案例如下:
let fibs = [1, 1, 2, 3, 5, 8, 13]
if let fidx = fibs.search([3, 5]) {
print(fibs[..<fidx]) // prints "[1, 1, 2]\n"
print(fidx..<fidx.advancedBy([1,1,5].count)) // prints "3..<6\n"
}
if let rng = fibs.rangeOf([5,8,13]) {
print(rng) // prints "4..<7\n"
}
但是,在rangeOf函数中,而不是循环
for _ in pattern.startIndex..<pattern.endIndex {
end = end.advancedBy(1)
}
我希望能够使用声明
end = start.advancedBy(pattern.count, limit: self.endIndex)
或者
end = start.advancedBy(pattern.endIndex - pattern.startIndex, limit: self.endIndex)
(我确实认识到limit参数是多余的;省略它在下面没有区别。)最后两个编译都没有编译,错误cannot invoke 'advancedBy' with an argument list of type '(S.Index.Distance, limit: Self.Index)'
。我的问题是,为什么这两种形式都不可接受? (我想还有其他有效的问题,我是否已经正确地对扩展和函数的类型形成约束,但是因为一个版本有效,我现在忽略了它。)
答案 0 :(得分:1)
end = start.advancedBy(pattern.count, limit: self.endIndex)
无法编译,因为集合self
和pattern
需要
没有相同的Index
类型。
如果您向S.Index == Index
方法添加约束rangeOf()
,则会进行编译。