Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I loop over self in a Range extension?

Tags:

swift

I have this extension:

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 { // :(

        }
    }
}

For some reason, the first loop is fine, but the second isn't. I get a compile time error saying

Type 'Bound' does not conform to protocol 'Strideable'  

Something that's also interesting to note here is that assigning bar with self effects the error to pop up in the first loop.

like image 446
Kevin Wessels Avatar asked Jan 01 '23 00:01

Kevin Wessels


1 Answers

Make it explicit to the compiler that the Bound is Strideable :

extension Range where Element: Strideable {
    ...
}

Defining a Range only requires the Bound to only be Comparable. See the actual implementation here. Comparable is the minimum requirement to define a Range.

There are two types of ranges :

  • CoutableRanges: These are ranges over types (Bound) that conform to Strideable and use integer steps between elements. These ranges are treated like a Sequence, and thus can be used in for loop.

  • Normal ranges: These include Range and ClosedRange with Comparable elements only, and thus can't be iterated over.

This is explicitly given in this comment.

like image 105
ielyamani Avatar answered Jan 15 '23 00:01

ielyamani