[swift-evolution] Add a `clamp` function to Algorithm.swift

Xiaodi Wu xiaodi.wu at gmail.com
Fri Mar 10 18:05:26 CST 2017

Some days ago, Ben Cohen laid out the criteria for helper functions in the
Standard Library. Here's some of his very enlightening text and the six

The operation needs to carry its weight. Even once we have ABI stability,
> so the size of the std lib becomes less of a concern as it could ship as
> part of the OS, we still need to keep helper method growth under control.
> APIs bristling with methods like an over-decorated Xmas tree are bad for
> usability. As mentioned in the String manifesto, String+Foundation
> currently has over 200 methods/properties. Helpers are no good if you can’t
> find them to use them.

> 1. Is it truly a frequent operation?
> 2. Is the helper more readable? Is the composed equivalent obvious at a
> glance?
> 3. Does the helper have the flexibility to cover all common cases?
> 4. Is there a correctness trap with the composed equivalent? Is there a
> correctness trap with the helper?
> 5. Is there a performance trap with the composed equivalent? Or with the
> helper?
> 6. Does the helper actually encourage misuse?

The reasons I'm opposed to adding `clamp` are as follows:

It is trivially composed from `min` and `max`, with no correctness traps.

As the discussion above shows, there are correctness traps when you have a
`clamp` operation that takes open ranges, whereas the composed form using
`min` and `max` does not suffer from the same issue.

It encourages misuse, because Dave's desired use case (for indices) works
*only* for arrays and falls down for collections. This is similar to the
problem which motivates removal of `enumerated()` as discussed in other
threads. In this case, it is not guaranteed that a collection with indices
`0..<10` has an index 9.

On Fri, Mar 10, 2017 at 4:48 PM, James Froggatt via swift-evolution <
swift-evolution at swift.org> wrote:

> This topic caught my attention. I support the idea, I'm currently using an
> extension for this.
> >>Should “16.clamped(to: 0..<10)” produce 9 or 10?
> >9
> Sounds good.
> >>What about “16.clamped(to: 0..<0)”, which is an empty range?
> >For `Int`? Crash (which, until about 5 minutes ago, is what I thought
> would happen if you tried to create a range that’s empty like that). For
> types that support it, I’d say NaN or something like “nil”/“empty” is the
> most appropriate return value
> Nasty but reasonable. I'd support it returning nil in this case, this
> would provide a warning that the result may not be a valid number, as well
> as providing this elegant range validation:
> `if let index = candidate.clamped(to: array.indices) { … }`
> (or a possible alternative spelling:)
> `if let index = array.indices.clamp(candidate) { … }`
> >>Does “16.0.clamped(to: 0..<10)” yield 10.0 or the next-smaller
> representable Double?
> >Next-smaller, IMHO. It’s not exactly semantically correct, but AFAIK
> that’s as correct as Float/Double can be.
> One could argue the most ‘correct’ value here is the closest
> representation of the theoretical value, `10.0 - (1 / ∞)`, which should
> clearly round to 10. However, this also rounds the result back out of the
> range, meaning it's unsuitable as a result. Both possibilities are, for
> lack of a better word, ugly.
> >Mostly though I’d really like to be able to clamp to array indices, which
> are pretty much always written as a `Range`, rather than a `ClosedRange`.
> We could write the function for `Range` to only be generic over
> `Comparable&Integer`, if the floating point corner cases are too much.
> > - Dave Sweeris
> My conclusion also. I'd like to see this added to the standard library, if
> it's in scope for Swift 4.
> Sidenote: I can't help but think index validation would be better solved
> in many cases by an optional-returning array subscript (`array[ifPresent:
> index]`), but I've seen this solution turned down several times due to the
> lack of discoverability (read: lack of Xcode autocompletion, which I
> originally thought was a bug until it stayed that way for ~3 years). I'd
> also like to see this feature get added in some form, eventually.
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170310/51da2b70/attachment.html>

More information about the swift-evolution mailing list