0

Custom Range Operators

Swift 4.1, Xcode 9.3

I am looking to make two custom range operators: <.., <.<


1. <..

  • This operator will be sort of the inverse of the ..< range operator.

My Attempt:

infix operator <.. : RangeFormationPrecedence

public func <.. (lhs: Int, rhs: Int) -> Range {
    return lhs - 1 ... rhs
}

Errors:

1. Custom Range Operator Error

Note: I also get about an additional 22 compile time errors surrounding the actual declaration of the custom operator (<..) itself.

Ideal Usage:

for i in 1<..9 {
    print(i, terminator: " ")
}

// Prints "0 1 2 3 4 5 6 7 8 9"

2. <.<

  • I want to make sort of a combination of my previous custom range operator. <.. and ..<

My Attempt:

infix operator <.< : RangeFormationPrecedence

public func <.< (lhs: Int, rhs: Int) -> Range {
    return lhs - 1 ..< rhs
}

Errors:

2. Custom Range Operator Error

Note: I also get about an additional 22 compile time errors surrounding the actual declaration of the custom operator (<.<) itself.

Ideal Usage:

for i in 1<.<10 {
    print(i, terminator: " ")
}

// Prints "0 1 2 3 4 5 6 7 8 9"

How can I accomplish this?

Also, what type of Range should I be returning?

Lastly, are there any preconditions that need to be added to the custom range operators themselves to ensure safety?


Update

I decided to create two operators (1x postfix, 1x infix) to accomplish one of these goals:

postfix operator <

public postfix func < <T: Numeric>(n: T) -> T { return n - 1 }


infix operator .< : RangeFormationPrecedence

public func .< <T: Numeric>(lhs: T, rhs: T) -> CountableRange<T> {
    return lhs ..< rhs
}

Then I can do:

for i in 1<.<10 {
    print(I, terminator: " ")
}

//Prints "0 1 2 3 4 5 6 7 8 9"

Caveat: I cannot have a space between the numbers and the operators (i.e. 1 <.< 10)


Noah Wilder
  • 1,656
  • 20
  • 38

1 Answers1

3

<.. and <.< are not valid identifiers for operators. You'll find the details in Operators in the Swift language reference.

Mimicking the declaration of the existing

extension Strideable where Self.Stride : SignedInteger {
    public static func ... (minimum: Self, maximum: Self) -> CountableClosedRange<Self>
}

operator, your first custom operator can be implemented as

infix operator <!! : RangeFormationPrecedence

extension Strideable where Self.Stride : SignedInteger {
    public static func <!! (minimum: Self, maximum: Self) -> CountableClosedRange<Self> {
        return minimum.advanced(by: -1) ... maximum
    }
}

Example:

for i in 1<!!9 { print(i, terminator: " ") }
// 0 1 2 3 4 5 6 7 8 9

The second operator can be implemented in a similar fashion, using CountableRange instead of CountableClosedRange.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Why would I make an extension rather than an operator? – Noah Wilder May 01 '18 at 17:20
  • 1
    @NoahWilder: All operators are functions. The question is: why an extension method and not a free function? I just looked up how `...` is defined. You can also define a free function `public func <!! (minimum: T, maximum: T) -> CountableClosedRange where T.Stride: SignedInteger` – I don't think that it makes a difference. – Martin R May 01 '18 at 17:24
  • I just though of another solution; what do you think? Also, do you have any idea how to make it so I can indeed have a space? @MartinR – Noah Wilder May 01 '18 at 17:47
  • @NoahWilder: There are also rules for spaces around operators, see for example https://stackoverflow.com/questions/31301715/what-are-the-rules-for-spaces-in-swift. That's why `for i in 1 <.< 10` does not compile. – Martin R May 01 '18 at 18:23
  • Don't mean to push @MartinR, but do you have any suggestions or workarounds to do something of the likes of what I would like to do? – Noah Wilder May 02 '18 at 00:49
  • @NoahWilder: I have tried to answer your (initial) question. `<!!` was just an example to demonstrate how the operator can be defined .There are a lot of allowed Unicode characters which you can choose from. – Defining two operators for that purpose (where `.<` is just an alias for `..<`) is confusing in my opinion, and has “unexpected“ behavior with respect to spacing, as you noticed. – Martin R May 02 '18 at 05:51
  • Thank you @MartinR – Noah Wilder May 02 '18 at 16:56