Reverse Range in Swift

前端 未结 7 1325
青春惊慌失措
青春惊慌失措 2020-11-27 14:07

Is there a way to work with reverse ranges in Swift?

For example:

for i in 5...1 {
  // do something
}

is an infinite loop.

7条回答
  •  盖世英雄少女心
    2020-11-27 15:09

    There's something troubling about the asymmetry of this:

    for i in (1..<5).reverse()
    

    ...as opposed to this:

    for i in 1..<5 {
    

    It means that every time I want to do a reverse range, I have to remember to put the parentheses, plus I have to write that .reverse() on the end, sticking out like a sore thumb. This is really ugly in comparison to C-style for loops, which are symmetrical counting up and counting down. So I tended to use C-style for loops instead. But in Swift 2.2, C-style for loops are going away! So I've had to scurry around replacing all my decrementing C-style for loops with this ugly .reverse() construct — wondering all the while, why on earth isn't there a reverse-range operator?

    But wait! This is Swift — we're allowed to define our own operators!! Here we go:

    infix operator >>> {
        associativity none
        precedence 135
    }
    
    func >>> (end:Pos, start:Pos)
        -> ReverseRandomAccessCollection<(Range)> {
            return (start..

    So now I'm allowed to say:

    for i in 5>>>1 {print(i)} // 4, 3, 2, 1
    

    This covers just the most common case that occurs in my code, but it is far and away the most common case, so it's all I need at present.

    I had a kind of internal crisis coming up with the operator. I would have liked to use >.., as being the reverse of ..<, but that's not legal: you can't use a dot after a non-dot, it appears. I considered ..> but decided it was too hard to distinguish from ..<. The nice thing about >>> is that it screams at you: "down to!" (Of course you're free to come up with another operator. But my advice is: for super symmetry, define <<< to do what ..< does, and now you've got <<< and >>> which are symmetrical and easy to type.)


    Swift 3 version (Xcode 8 seed 6):

    infix operator >>> : RangeFormationPrecedence
    func >>>(maximum: Bound, minimum: Bound) ->
        ReversedRandomAccessCollection> 
        where Bound : Comparable, Bound.Stride : Integer {
            return (minimum..

    Swift 4 version (Xcode 9 beta 3):

    infix operator >>> : RangeFormationPrecedence
    func >>>(maximum: Bound, minimum: Bound)
        -> ReversedRandomAccessCollection>
        where Bound : Comparable & Strideable { 
            return (minimum..

    Swift 4.2 version (Xcode 10 beta 1):

    infix operator >>> : RangeFormationPrecedence
    func >>>(maximum: Bound, minimum: Bound)
        -> ReversedRandomAccessCollection>
        where Bound : Strideable { 
            return (minimum..

    Swift 5 version (Xcode 10.2.1):

    infix operator >>> : RangeFormationPrecedence
    func >>>(maximum: Bound, minimum: Bound)
        -> ReversedCollection>
        where Bound : Strideable {
            return (minimum..

提交回复
热议问题