我有这个扩展名:
extension Range {
func foo() { // called with (0..<5).foo()
let bar = 0..<5
print(bar) // 0..<5
print(self) // 0..<5
print(type(of: bar)) // Range<Int>
print(type(of: self)) // Range<Int>
for i in bar { // :)
}
for j in self { // :(
}
}
}
由于某种原因,第一个循环很好,但第二个循环则不好。我收到一个编译时错误消息
Type 'Bound' does not conform to protocol 'Strideable'
在这里还要注意的一点是,将bar
分配给self
会导致错误在第一个循环中弹出。
答案 0 :(得分:5)
向编译器明确表明Bound
是Strideable
:
extension Range where Element: Strideable {
...
}
定义Range
仅要求Bound
仅是Comparable
。请参阅实际实现here。 Comparable
是定义Range
的最低要求。
有两种类型的范围:
CoutableRange
s:这些是符合Bound
的类型(Strideable
)上的范围,并且在元素之间使用整数步长。这些范围被视为Sequence
,因此可以在for
循环中使用。
普通范围:这些范围仅包含Range
个元素的ClosedRange
和Comparable
,因此无法进行迭代。
这在this注释中明确给出。
答案 1 :(得分:4)
在bar
示例中,编译器知道bar
是0..<5
。但是在self
示例中,编译器不知道self
是什么。
所以现在考虑以下代码:
for i in 0.0..<1.0 {}
它不能编译。为什么不?因为通过for...in
在Double范围内循环的整个概念没有意义。
好吧,在您的代码中,编译器不知道您的Range(self
)不会是Double的范围。您必须保证不会。因此,您必须指定扩展名仅在for...in
有意义的范围内起作用。
您可以通过指定这是Int或SignedInteger的范围来做到这一点,但是最一般的指定方法是说您的范围是一个可跨越的范围。