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

Neil Cowburn neil at neilcowburn.com
Wed Mar 15 05:22:15 CDT 2017

A suggestion, if I may: change the verb `clamped` to `bound`. The verb `clamp` means to immobilise or fix in place. That seems counterintuitive given the sole function argument is a range. 

Compare the interpretation of clamped vs bound: 

foo.clamped(to: 0...100) --> “The integer, foo, is clamped to a range between 0 and 100”

foo.bound(to: 0...100) --> “The integer, foo, is bound to a range between 0 and 100”

The latter, to me, reads more naturally than the former. 

-- Neil

On 15/03/2017, 02:07, "Nicholas Maccharoli via swift-evolution" <swift-evolution-bounces at swift.org on behalf of swift-evolution at swift.org> wrote:

    I am starting to worry that I left something out.
    On Tue, Mar 14, 2017 at 11:16 AM, Nicholas Maccharoli <nmaccharoli at gmail.com> wrote:
    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:
    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>IntroductionThis 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>MotivationThere 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 solutionThe 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 designThe 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 compatibilityThis 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 stabilityThis 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 resilienceThe 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 consideredAside from doing nothing, no other alternatives were considered.
    swift-evolution mailing list
    swift-evolution at swift.org

More information about the swift-evolution mailing list