[swift-evolution] [draft] Add `clamped(to:)` to the stdlib

Nicholas Maccharoli nmaccharoli at gmail.com
Wed Mar 15 21:33:49 CDT 2017


Right, there were a few things missing!
Thanks so much for pointing them out everyone.

Dave - Great idea! I have updated the motivation section section as you
suggested!

Neil - Yes I also think the wording could be a bit better but since the
word `clamped` is already being used
          I thought I would keep it consistent.

Sean - Looks as if its a term of art to me as well.

Nate,

Good catch! Yes I also thing clamping on an empty range should be a fatal
error as well.
An empty range is impossible to create with `ClosedRange` so I left the
implementation
of that alone, but it is possible with `Range` so I updated the extension
on `Strideable` like so:

extension Strideable where Stride: Integer {
    func clamped(to range: Range<Self>) -> Self {
        if range.isEmpty { fatalError("Can't form Range with
upperBound < lowerBound") }
        return clamped(to: range.lowerBound...(range.upperBound - 1))
    }
}




Jaden,

Yeah I think a simple `if` check would work as well.


On Thu, Mar 16, 2017 at 10:19 AM, Jaden Geller <jaden.geller at gmail.com>
wrote:

>
> On Mar 15, 2017, at 12:40 PM, Nate Cook via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Hi Nick,
>
> I think this might have come up in an earlier thread, but clamped(to:)
> with a half-open range argument brings up the question of how to clamp to
> an empty range. As proposed, the implementation of this method would result
> in an error when passed an empty range:
>
>     foo.clamped(to: 0..<0)
>     // fatal error: Can't form Range with upperBound < lowerBound
>
>
> Ahh, good catch! The implementation ought to add something like:
>
> guard !range.isEmpty else { fatalError("Cannot clamp to an empty range") }
>
> I don’t think that this is problematic. Ideally we could express in the
> type-system that the range must not be empty, but it is definitely not
> worthwhile creating a `NonemptyRange` type.
>
>
> Is that the desired behavior? Providing documentation for both new methods
> would help make it clear what the expected functionality is.
>
> Thanks!
> Nate
>
>
> On Mar 13, 2017, at 9:16 PM, Nicholas Maccharoli via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Swift-Evolution,
>
> After considering the indispensable feedback from the community here is a
> slightly more polished draft.
>
> If anyone is interested the draft can be downloaded here:
> https://github.com/Nirma/swift-evolution/blob/clamp_function
> /proposals/NNNN-add-clamp-function.md
>
> Thank you so much,
>
> - Nick
>
>
> Add clamp(to:) to the stdlib
>
>    - Proposal: SE-NNNN
>    <https://github.com/Nirma/swift-evolution/blob/clamp_function/proposals/NNNN-filename.md>
>    - Authors: Nicholas Maccharoli <https://github.com/Nirma>
>    - Review Manager: TBD
>    - Status: Awaiting review
>
> *During the review process, add the following fields as needed:*
>
>    - Decision Notes: Rationale
>    <https://lists.swift.org/pipermail/swift-evolution/>, Additional
>    Commentary <https://lists.swift.org/pipermail/swift-evolution/>
>    - Bugs: SR-NNNN <https://bugs.swift.org/browse/SR-NNNN>, SR-MMMM
>    <https://bugs.swift.org/browse/SR-MMMM>
>    - Previous Revision: 1
>    <https://github.com/apple/swift-evolution/blob/...commit-ID.../proposals/NNNN-filename.md>
>    - Previous Proposal: SE-XXXX
>    <https://github.com/Nirma/swift-evolution/blob/clamp_function/proposals/XXXX-filename.md>
>
>
> <https://github.com/Nirma/swift-evolution/blob/clamp_function/proposals/NNNN-add-clamp-function.md#introduction>
> Introduction
>
> This proposal aims to add functionality to the standard library for
> clamping a value to a ClosedRange. The proposed function would allow the
> user to specify a range to clamp a value to where if the value fell within
> the range, the value would be returned as is, if the value being clamped
> exceeded the upper or lower bound in value the value of the boundary the
> value exceeded would be returned.
>
> Swift-evolution thread: Add a clamp function to Algorithm.swift
> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170306/thread.html#33674>
>
> <https://github.com/Nirma/swift-evolution/blob/clamp_function/proposals/NNNN-add-clamp-function.md#motivation>
> Motivation
>
> There have been quite a few times in my professional and personal
> programming life where I reached for a clampedfunction and was
> disappointed it was not part of the standard library.
>
> Having functionality like clamped(to:) added to Comparable as a protocol
> extension would benefit users of the Swift language who wish to guarantee
> that a value is kept within bounds.
>
> <https://github.com/Nirma/swift-evolution/blob/clamp_function/proposals/NNNN-add-clamp-function.md#proposed-solution>Proposed
> solution
>
> The solution proposed is simply that there be a clamped(to:) function
> added to the Swift Standard Library. The function would behave much like
> its name describes.
>
> Given a clamped(to:) function existed it could be called in the following
> way, yielding the results in the adjacent comments:
>
> let foo = 100
> // Closed range variant
> foo.clamped(to: 0...50) // 50foo.clamped(to: 200...300) // 200foo.clamped(to: 0...150) // 100// Half-Open range variant
> foo.clamped(to: 0..<50) // 49foo.clamped(to: 200..<300) // 200foo.clamped(to: 0..<150) // 100
>
>
> <https://github.com/Nirma/swift-evolution/blob/clamp_function/proposals/NNNN-add-clamp-function.md#detailed-design>Detailed
> design
>
> The implementation of clamped(to:) that is being proposed is composed of
> two protocol extensions; one protocol extension on Comparable and another
> on Strideable.
>
> The implementation for clamped(to:) as an extension to Comparable accepting
> a range of type ClosedRange<Self>would look like the following:
>
> extension Comparable {
>     func clamped(to range: ClosedRange<Self>) -> Self {
>         if self > range.upperBound {
>             return range.upperBound
>         } else if self < range.lowerBound {
>             return range.lowerBound
>         } else {
>             return self
>         }
>     }
> }
>
> The implementation of clamped(to:) as an extension on Strideable would be
> confined to cases where the stride is of type Integer. The implementation
> would be as follows:
>
> extension Strideable where Stride: Integer {
>     func clamped(to range: Range<Self>) -> Self {
>         return clamped(to: range.lowerBound...(range.upperBound - 1))
>     }
> }
>
>
> <https://github.com/Nirma/swift-evolution/blob/clamp_function/proposals/NNNN-add-clamp-function.md#source-compatibility>Source
> compatibility
>
> This feature is purely additive; it has no effect on source compatibility.
>
> <https://github.com/Nirma/swift-evolution/blob/clamp_function/proposals/NNNN-add-clamp-function.md#effect-on-abi-stability>Effect
> on ABI stability
>
> This feature is purely additive; it has no effect on ABI stability.
>
> <https://github.com/Nirma/swift-evolution/blob/clamp_function/proposals/NNNN-add-clamp-function.md#effect-on-api-resilience>Effect
> on API resilience
>
> The proposed function would become part of the API but purely additive.
>
> <https://github.com/Nirma/swift-evolution/blob/clamp_function/proposals/NNNN-add-clamp-function.md#alternatives-considered>Alternatives
> considered
> Aside from doing nothing, no other alternatives were considered.
> _______________________________________________
> 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/20170316/6ccbcf10/attachment.html>


More information about the swift-evolution mailing list