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

李海珍 banxi1988 at gmail.com
Sat Mar 11 01:39:30 CST 2017


Hi, I think a func such as clamped would be helpful. to be frank, I had
made some mistakes when trying to compose min and max correctly.


Robert Bennett via swift-evolution <swift-evolution at swift.org>于2017年3月11日周六
下午1:35写道:

> I can't argue with that. I guess I was really only opposed to using the
> half-open range for Double and other theoretically non-discrete types, for
> the reasons I listed. I have no objections to clamping with a half-open
> Integer range; I just hadn't considered further restricting the Bound of
> the Range in use. arr[idx.clamped(to: arr.indices)] looks amazing.
>
> On Mar 11, 2017, at 12:29 AM, Jaden Geller <jaden.geller at gmail.com> wrote:
>
>
> On Mar 10, 2017, at 8:04 PM, Robert Bennett via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I really like this proposal, and think that it does have a place in Swift
> 4. Two quick notes in light of the discussion: first, I think it should be
> called clamped, not clamp; second, I think it should only take ClosedRange.
> More on those later, but first I'll respond to the six questions raised by
> Xiaodi.
>
> 1. Is it truly a frequent operation?
>
> I think so. I've certainly wished for it on an occasion or two. I settle
> for min(upper, max(lower, value)).
>
> 2. Is the helper more readable? Is the composed equivalent obvious at a
> glance?
>
> Definitely (or I imagine it will be once we get the details figured out).
> There are two equivalent forms of the min-max version, the other being
> max(lower, min(upper, value)), not to mention the commutativity of the
> arguments themselves. I am under the impression that Swift is not a big fan
> of having multiple equivalent ways to do the same thing — that was part of
> the reason ++ was nixed. value.clamp(to: closedRange) is clear and is not
> interchangeable with any one thing in the language.
>
> 3. Does the helper have the flexibility to cover all common cases?
>
> I see three cases: value < lower, lower <= value <= upper, and upper <
> value. All are covered.
>
> 4. Is there a correctness trap with the composed equivalent? Is there a
> correctness trap with the helper?
>
> I don't think so, if we limit to ClosedRange.
>
> 5. Is there a performance trap with the composed equivalent? Or with the
> helper?
>
> I don't know, is there a significant cost associated to constructing a
> ClosedRange solely for the purpose of using its bounds? I would imagine
> not, but someone who knows more about Swift can answer.
>
> 6. Does the helper actually encourage misuse?
>
> I don't see how, if we limit its argument to ClosedRange.
>
>
> Going back to my earlier points — I think that to keep things in line with
> Swift's naming conventions, this function should be called clamped, as it
> returns a modified version of the calling object. Alternatively, we could
> follow the standard set by other numeric types and provide the non-mutating
> clamped and the mutating clamp, like multiplied/multiply for Double.
>
> Finally, I don't think it makes mathematical sense to clamp to a
> non-closed range. Refer back to the original definition proposed,
> `min(upperBound, max(lowerBound, value))`. ClosedRange was proposed as a
> convenience for providing those bounds. This makes sense because a
> ClosedRange contains its bounds. Since (mathematical) non-closed ranges
> don't contain their bounds, it doesn't make sense to use a non-closed range
> to provide those bounds.
>
>
> I think open ranges should be supported, but not for all `Comparable`
> types. It would however be reasonable to support it for types with discrete
> ordered values, all `Integer` types for example. I think we might be able
> to provide it for `T: Strideable where T.Stride: Integer` even. We
> definitely cannot provide it for all types though; it’s nonsensical to
> clamp a real value to a closed range.
>
>
> Also, the above notwithstanding, I have a hard time figuring out when you
> would actually want to constrain a number to be strictly less than an upper
> bound, violating Question 1 above. If this behavior were really desired,
> better to be explicit and subtract the appropriate delta — 1 for Int,
> Double.epsilon (or whatever it's called) for Double. I definitely foresee a
> correctness trap with the non-closed Range.
>
> Another reason not to allow half-open ranges is because of their
> asymmetry. Half open ranges are only open at their upper end, so you would
> have the ability to open-clamp from above but not from below. Seems
> arbitrary (see Question 3).
>
>
> We already have this asymmetry. Adding a clamp function doesn’t worsen it.
> Besides, we have half-open [above] ranges because they are useful for
> indices:
>
> `arr[idx.clamped(to: arr.startIndex..<arr.endIndex)`
>
> We can even write this!
>
> `arr[idx.clamped(to: arr.indices)]`
>
> This seems like a useful enough feature to consider it IMO.
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> 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/20170311/525cca35/attachment.html>


More information about the swift-evolution mailing list