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
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)
}
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
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.