Add a `clamp` function to Algorithm.swift

In my opinion, one more scenario should be covered.

func doSomething(val1: Double, val2: Double) {
  let offset = 10.clamped(to: val1...val2)
}

If val1 > val2, the app will crash with error "Can't form Range with upperBound < lowerBound"
To prevent this, we are forced to check that val1 < val2 every time, which is annoying.

To prevent this, we can make one more clamped(to:) overload:

func clamped(_ lhs: Self, _ rhs) -> Self {
    guard lhs != rhs else { return lhs }

    var lower = lhs
    var upper = rhs

    if rhs < lhs {
      swap(&lower, &upper)
    }

    return min(upper, max(self, lower))
}

What do you think?

You'd have the same issue with any API taking ClosedRange or Range.

Double.random(in: val1...val2)

The solution is simple enough that I don't think it needs additional APIs.

Double.random(in: val1 <= val2 ? val1...val2 : val2...val1)

But you could pitch init(unorderedBounds:) as a separate proposal.

Double.random(in: ClosedRange(unorderedBounds: val1, val2))
2 Likes

Right, this is fundamentally part of how ranges work in Swift, and not something that this API should be working around.

2 Likes

Great idea, I have created a separate pitch: ClosedRange init with unordered bounds

Has there been any progress on this? Would love to have this function available.

1 Like

@John_McCall As mentioned on Github I want to continue the conversation here on this thread before opening a new PR.

I still think this would be a great idea and very useful and there is discussion among community members but not too much back and forth with members of the core team.

Maybe things are a bit more stable now so we can go over this proposal again?

Thanks!

1 Like

That makes sense to me. Feel free to open whenever you think it’s ready. Maybe @scanon can get more eyes from his team on it.

Thoughts on spelling this .bounded(within: some RangeExpression<Self>)?

(Where some RangeExpression<Self> are overloads for every Range type that would make sense to bound a value by, e.g. ClosedRange, PartialRangeFrom, & PartialRangeThrough)

clamped is better than bounded, because bounded does not suggest as clearly what happens for values that are outside the range.

8 Likes

Has this proposal progressed at all since this post? I think these functions would be useful.

1 Like