为什么我不能在Range扩展中自我循环?

时间:2019-05-01 14:16:16

标签: swift

我有这个扩展名:

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会导致错误在第一个循环中弹出。

2 个答案:

答案 0 :(得分:5)

向编译器明确表明BoundStrideable

extension Range where Element: Strideable {
    ...
}

定义Range仅要求Bound仅是Comparable。请参阅实际实现hereComparable是定义Range的最低要求。

有两种类型的范围:

  • CoutableRange s:这些是符合Bound的类型(Strideable)上的范围,并且在元素之间使用整数步长。这些范围被视为Sequence,因此可以在for循环中使用。

  • 普通范围:这些范围仅包含Range个元素的ClosedRangeComparable,因此无法进行迭代。

这在this注释中明确给出。

答案 1 :(得分:4)

bar示例中,编译器知道bar0..<5。但是在self示例中,编译器不知道self是什么。

所以现在考虑以下代码:

for i in 0.0..<1.0 {}

它不能编译。为什么不?因为通过for...in在Double范围内循环的整个概念没有意义。

好吧,在您的代码中,编译器不知道您的Range(self)不会是Double的范围。您必须保证不会。因此,您必须指定扩展名仅在for...in有意义的范围内起作用。

您可以通过指定这是Int或SignedInteger的范围来做到这一点,但是最一般的指定方法是说您的范围是一个可跨越的范围。