2

In Swift3,

let highestIndex = 7
for index in 1 ..< highestIndex {
    latter(index)
}

however,

let highestIndex = 0, or anything smaller
for index in 1 ..< highestIndex {
    latter(index)
}

that crashes.

So, the ..< operator is impractical in most situations.

So, perhaps, something like this ...

for index in (1 ..< highestIndex).safely() {
    latter(index)
}

How would one write the extension safely ?

Or at worst just a function safely(from,to) which returns a CountableRange, or, an "empty" (?) countable range? (I don't understand if a Swift extension can "catch" an error?)

Fattie
  • 27,874
  • 70
  • 431
  • 719
  • "*Is there such a thing as an "empty" countable range*" – yes, `1..<1` is just that (it does not crash). – Hamish Feb 05 '17 at 22:49
  • 1
    If you don't want the loop to be entered if the upper bound is less than the lower bound, `stride` is a good alternative – see for example http://stackoverflow.com/a/36861439/2976878 – Hamish Feb 05 '17 at 22:52
  • [DOH facepalm](http://cdn.onegreenplanet.org/wp-content/uploads/2010/10/2014/11/lead1.jpg) -- **stride**, of course, that's the way to go. you've cracked it again, @Hamish – Fattie Feb 05 '17 at 22:55

3 Answers3

2

Sticking as closely to the ..< operator as possible the following would be an appropriate implementation of safely.

public func safely<Bound>(_ minimum: Bound, _ maximum: Bound) -> CountableRange<Bound> where Bound : _Strideable & Comparable, Bound.Stride : Integer {
    if maximum < minimum {
        return CountableRange(uncheckedBounds: (lower: minimum, upper: minimum))
    }
    return CountableRange(uncheckedBounds: (lower: minimum, upper: maximum))
}

let one = safely(0, 12)  // CountableRange(0..<12)
let two = safely(15, 12) // CountableRange(15..<15)

one.isEmpty // false
two.isEmpty // true

You might want to consider giving the parameters better names to indicate wether or not they are inclusive / exclusive bounds, etc.

Creating an extension and adding a .safely() will not work since the bounds are checked when creating the CountableRange before the call to safely could even be done.

luk2302
  • 55,258
  • 23
  • 97
  • 137
  • Say, in your excellent code. I'd suggest, the first return should just be "return 0..<0". Emphasizing the fact that you're just returning "no trips". Great stuff. – Fattie Feb 05 '17 at 22:56
1

I'm able to get this to work fine:

for index in 1 ..< 1 {
    latter(index)
}

For the <1 case, I recommend something like this:

guard highestIndex > 0 else { return }

for index in 1 ..< highestIndex {
    latter(index)
}
Mark
  • 7,167
  • 4
  • 44
  • 68
  • Hey Mark - thanks for that. Sure, "guard" is a terrific feature. But, you know, it's no good for inline code; the most natural situation is that of course, you just want it to "not do any iterations" if the value is too low.... – Fattie Feb 05 '17 at 22:47
1

I am a fan of simple solutions:

let lowerIndex = 1
let higherIndex = 0
for index in lowerIndex ..< max(lowerIndex, higherIndex) {
    latter(index)
}
Sulthan
  • 128,090
  • 22
  • 218
  • 270