swiftswift2protocolsprotocol-extensionclamp

Extending Generic Integer Types in Swift


So I'm trying to extend Swift's integer types with a few convenient functions that I use a lot, however I'm not clear on which protocols I should be extending.

As an example, let's say I want to implement a function for clamping a value (if it's less than a minimum set it to that, otherwise if it's greater than a maximum then set it to that instead). My first thought was to do something like this:

extension Int {
    func clamp(minimum:Int, maximum:Int) {
        if self < minimum { return minimum }
        if self > maximum { return maximum }
        return self
    }
}

Bit of a simplistic example, but it illustrates the problem; if I want to now call this for a UInt then naturally I can't, so I have to add an equivalent to UInt, but that won't work for a UInt16 and so-on.

I thought that I could perhaps extend something higher up the chain, and use generics instead, however protocols such as IntegerType can't seem to be extended.

So, is there somewhere more appropriate that I could put my extension(s)?


Solution

  • For Swift 2, see Andriy Gordiychuk's answer, which will be correct then. If you require Swift 1, then this cannot be done with extensions, and must be done with free functions. This is why there are so many free functions in stdlib that became extensions in Swift 2.

    For Swift 1, what you have to do is:

    func clamp<T:Comparable>(value: T, #minimum:T, #maximum:T) -> T {
        if value < minimum { return minimum }
        if value > maximum { return maximum }
        return value
    }
    

    If you prefer modifying the value (as Andriy's example does), you can do it this way:

    func clamp<T:Comparable>(inout value: T, #minimum:T, #maximum:T) {
        if value < minimum { value = minimum }
        else if value > maximum { value = maximum }
    }
    

    Otherwise you have to write an extension on every type. It's the only other answer in Swift 1. Swift 2 is much better.