How can I use an open range (both bounds exclusive) in Swift?

Issue

I already know that there’s a built-in operator ..< called half-open range. But how can I obtain a "both-open" range, meaning a range that doesn’t contain either terminal?

To clarify using interval notation, if a...b is equivalent to [a, b] and a..<b is equivalent to [a, b), what is the Swift equivalent of (a, b)?

Ideally, I would prefer to do this using native Swift functionality. But if this is not possible, could I extend Range to achieve this?

I tried in some ways, but I still don’t know how.

Solution

As regards extending Range, SwiftLee author Antoine Van Der Lee describes how to define custom operators here: https://www.avanderlee.com/swift/custom-operators-swift/

Using the Custom Infix Operator example from the linked blog post as a template, I came up with this extension to define your ‘both-open’ range:

import Foundation

infix operator >-<: RangeFormationPrecedence
extension Int {
    static func >-< (lhs: Int, rhs: Int) -> ClosedRange<Int> {
        return ClosedRange(uncheckedBounds: (lower: lhs + 1, upper: rhs - 1))
    }
}

for i in 5>-<8 {
    print(i)
}

Note that although the result is a Range (specifically a ClosedRange<Int>), the operator itself is actually defined on Int.

Running the above example code in a Swift Playground produces the output

6
7

so you can see that by using the custom infix operator >-<, the resulting ‘both-open’ range starts from a number 1 greater than the lower bound, and goes up to a number 1 less than the upper bound.

(I tried defining the operator as >.< to parallel the half-open range operator ..<, but Xcode objected.)

Answered By – Quack E. Duck

Answer Checked By – Clifford M. (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.