Elegant `bounded` methodology in Swift

前端 未结 3 1635
悲哀的现实
悲哀的现实 2021-01-23 11:09

I\'m looking for a more elegant way to create bounded limiters for numbers, primarily to be used in setters. There are plenty of techniques for determining whether a value falls

相关标签:
3条回答
  • 2021-01-23 11:30

    This is Apple's own approach, taken from this sample code:

    func clamp<T: Comparable>(value: T, minimum: T, maximum: T) -> T {
        return min(max(value, minimum), maximum)
    }
    
    0 讨论(0)
  • 2021-01-23 11:48

    I would generalize this extension to any Comparable, so that more types can benefit from it. Also, I would change the parameter to be a ClosedRange<Self> rather than two separate Self parameters, because that's the more common way of handling ranges in Swift. That'll come in especially handy when dealing with array indices.

    extension Comparable {
        func clamped(to r: ClosedRange<Self>) -> Self {
            let min = r.lowerBound, max = r.upperBound
            return self < min ? min : (max < self ? max : self)
        }
    }
    
    // Usage examples:
    10.clamped(to: 0...5) // => 5
    "a".clamped(to: "x"..."z") // => "x"
    -1.clamped(to: 0...1) // => 0
    
    0 讨论(0)
  • 2021-01-23 11:51

    A very clean alternative to your if-else statements, keeping the readability would be:

    extension Comparable{
        func clamp(_ min: Self,_ max: Self) -> Self{
            return min...max~=self ? self : (max < self ? max : min)
        }
    }
    

    I think this is a good alternative to using a range as parameter, because, in my opinion, it is annoying to write 6.clamp((4...5)) each time insted of 6.clamp(4,5).

    When it comes to your struct, I think you should not use this clamp extension at all, because, say, 100 does not mean 4... I cannot see the reason for doing this, but it's up to you.

    0 讨论(0)
提交回复
热议问题