On Fri, Mar 10, 2017 at 6:29 PM, James Froggatt <james.frogg...@me.com> wrote:
> > On 11 Mar 2017, at 00:21, James Froggatt <james.frogg...@me.com> wrote: > > > On 11 Mar 2017, at 00:05, Xiaodi Wu <xiaodi...@gmail.com> wrote: > > 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 > criteria: > > 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. > > > You make a good point, but then how exactly did the range-clamping > function make it into the standard library in the first place? I can't > think of frequent reason to want to clamp a range to within another range > putting my mind to it, yet a clamp function on the Bound type has uses with > arrays and offers a clear improvement to readability. Then there's the > (potential) correctness trap of mixing up min and max, which I find leads > me to need to double-check the logic after typing. > > Seeing those criteria just makes it all the more frustrating that the > range-clamping version is the one to have made the cut. > > > Rereading, you're point is that the range-clamping version does solve a > correctness trap (and that the Bound version does not?). Could you explain > how you reached to this conclusion? > I'm not making that point. I'm just pointing out that these are the current criteria for expanding the standard library. If, looking back, you feel that the existing `clamped(to:)` doesn't fit the criteria, then you can propose its removal. However, there are also standards for changing existing APIs in Swift 4. The first one is that "the existing syntax/API being changed must be actively harmful"--which is a bar that `clamped(to:)` doesn't meet, IMO. On Fri, Mar 10, 2017 at 4:48 PM, James Froggatt via swift-evolution < > swift-evolution@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@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution >> > >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution