[Proposal draft] Add `Clamp` function to standard library

Introduction

The aim of this proposal is to introduce clamp functionality to the swift
standard library. The clamp function would take a value and a upper and
lower bounds to clamp the value to, ensuring that the return value of the
function is within the range specified by the upper and lower bounds.
Swift-evolution thread: Discussion thread topic for that proposal
<https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160829/026748.html&gt;
<https://github.com/Nirma/swift-evolution/blob/clamp_proposal/proposals/NNNN-add-clamp-to-standard-library.md#motivation&gt;
Motivation

The standard library already includes functionality for min and max but at
the time of this writing there is no global function for clamp. Adding a
clamp function would complement min and max really well and would also
eliminate the need for developers to write their own clamp functionality.
<https://github.com/Nirma/swift-evolution/blob/clamp_proposal/proposals/NNNN-add-clamp-to-standard-library.md#proposed-solution&gt;Proposed
solution

I propose that a global clamp function akin to min and max be added to the
standard library.
<https://github.com/Nirma/swift-evolution/blob/clamp_proposal/proposals/NNNN-add-clamp-to-standard-library.md#detailed-design&gt;Detailed
design

The implementation of the global clamp function would be as follows:

public func clamp<T : Comparable>(value: T, _ lower: T, _ upper: T) -> T {
  return max(lower, min(value, upper))
}

<https://github.com/Nirma/swift-evolution/blob/clamp_proposal/proposals/NNNN-add-clamp-to-standard-library.md#impact-on-existing-code&gt;Impact
on existing code

There are no impacts on existing code, this proposal is purely additive.
<https://github.com/Nirma/swift-evolution/blob/clamp_proposal/proposals/NNNN-add-clamp-to-standard-library.md#alternatives-considered&gt;Alternatives
considered

Aside from not making the additions that this proposal wishes to make to
the standard library no other alternatives have been considered.

Besides my concern that this is not in scope for Swift 4 phase 1, or for
the standard library generally, the function as proposed is unsatisfactory
because the behavior is incorrect when lower > upper.

Either

(a) the parameters should be labeled (and for consistency with ranges,
those labels should be "lowerBound" and "upperBound") and a precondition
should exist before evaluation of the return value, or

(b) this function should take two arguments, one of these being a Range, or

(c) better still--this should be a method on numeric types or on Range. I'm
not convinced that there is a use case for clamping values of any
Comparable type. What does it mean to clamp a String, for example?

Finally, it could possibly be more performant to compute the value using
the comparison operators < and > directly instead of using the functions
max and min. It would be nice to have benchmarks on that.

But I am still not convinced that this function is important enough *and*
susceptible enough to an incorrect implementation that the standard library
should provide its own.

···

On Fri, Sep 2, 2016 at 11:56 Nicholas Maccharoli via swift-evolution < swift-evolution@swift.org> wrote:

Introduction

The aim of this proposal is to introduce clamp functionality to the swift
standard library. The clamp function would take a value and a upper and
lower bounds to clamp the value to, ensuring that the return value of the
function is within the range specified by the upper and lower bounds.
Swift-evolution thread: Discussion thread topic for that proposal
<https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160829/026748.html&gt;

<https://github.com/Nirma/swift-evolution/blob/clamp_proposal/proposals/NNNN-add-clamp-to-standard-library.md#motivation&gt;
Motivation

The standard library already includes functionality for min and max but
at the time of this writing there is no global function for clamp. Adding
a clamp function would complement min and max really well and would also
eliminate the need for developers to write their own clamp functionality.

<https://github.com/Nirma/swift-evolution/blob/clamp_proposal/proposals/NNNN-add-clamp-to-standard-library.md#proposed-solution&gt;Proposed
solution

I propose that a global clamp function akin to min and max be added to
the standard library.

<https://github.com/Nirma/swift-evolution/blob/clamp_proposal/proposals/NNNN-add-clamp-to-standard-library.md#detailed-design&gt;Detailed
design

The implementation of the global clamp function would be as follows:

public func clamp<T : Comparable>(value: T, _ lower: T, _ upper: T) -> T {
  return max(lower, min(value, upper))
}

<https://github.com/Nirma/swift-evolution/blob/clamp_proposal/proposals/NNNN-add-clamp-to-standard-library.md#impact-on-existing-code&gt;Impact
on existing code

There are no impacts on existing code, this proposal is purely additive.

<https://github.com/Nirma/swift-evolution/blob/clamp_proposal/proposals/NNNN-add-clamp-to-standard-library.md#alternatives-considered&gt;Alternatives
considered

Aside from not making the additions that this proposal wishes to make to
the standard library no other alternatives have been considered.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

As others have pointed out, this is a purely additive change that is out of scope for Swift 4 stage 1. We need to keep standard library work focused on things like String.

-Chris

···

On Sep 2, 2016, at 9:55 AM, Nicholas Maccharoli via swift-evolution <swift-evolution@swift.org> wrote:

Introduction

The aim of this proposal is to introduce clamp functionality to the swift standard library. The clamp function would take a value and a upper and lower bounds to clamp the value to, ensuring that the return value of the function is within the range specified by the upper and lower bounds. Swift-evolution thread: Discussion thread topic for that proposal <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160829/026748.html&gt;

On some thought, Strideable rather than Comparable seems appropriate.
Strideable types have some meaningful concept of distance between two
values and would (or should, if they don't already?) include types like
Date. I like Strideable.clamped(to:) a lot, and the parallels with
Range.clamped(to:) make sense.

···

On Fri, Sep 2, 2016 at 15:58 David Rönnqvist via swift-evolution < swift-evolution@swift.org> wrote:

There is already a `clamped` function for clamping one range to another
and I feel that this function should be consistent with that one. As I see
it, it can either be consistent in that it takes a Range as its argument,
or in being an extension to Range. Probably something like either one of
these:

extension Comparable { // or something else?
    func clamped(to range: Range<Self>) -> Self
}

extension Range {
    func clamping(_ value: Bound) -> Bound
}

Involving a range is good because that means that ensuring that the bounds
checking (lower < upper) is already taken care of.

I do feel that this a useful addition to the standard library. But it is
purely additive, so it should wait until after Phase 1.

- David

Sent from my iPad

On 2 Sep 2016, at 18:55, Nicholas Maccharoli via swift-evolution < > swift-evolution@swift.org> wrote:

Introduction

The aim of this proposal is to introduce clamp functionality to the swift
standard library. The clamp function would take a value and a upper and
lower bounds to clamp the value to, ensuring that the return value of the
function is within the range specified by the upper and lower bounds.
Swift-evolution thread: Discussion thread topic for that proposal
<https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160829/026748.html&gt;

<https://github.com/Nirma/swift-evolution/blob/clamp_proposal/proposals/NNNN-add-clamp-to-standard-library.md#motivation&gt;
Motivation

The standard library already includes functionality for min and max but
at the time of this writing there is no global function for clamp. Adding
a clamp function would complement min and max really well and would also
eliminate the need for developers to write their own clamp functionality.

<https://github.com/Nirma/swift-evolution/blob/clamp_proposal/proposals/NNNN-add-clamp-to-standard-library.md#proposed-solution&gt;Proposed
solution

I propose that a global clamp function akin to min and max be added to
the standard library.

<https://github.com/Nirma/swift-evolution/blob/clamp_proposal/proposals/NNNN-add-clamp-to-standard-library.md#detailed-design&gt;Detailed
design

The implementation of the global clamp function would be as follows:

public func clamp<T : Comparable>(value: T, _ lower: T, _ upper: T) -> T {
  return max(lower, min(value, upper))
}

<https://github.com/Nirma/swift-evolution/blob/clamp_proposal/proposals/NNNN-add-clamp-to-standard-library.md#impact-on-existing-code&gt;Impact
on existing code

There are no impacts on existing code, this proposal is purely additive.

<https://github.com/Nirma/swift-evolution/blob/clamp_proposal/proposals/NNNN-add-clamp-to-standard-library.md#alternatives-considered&gt;Alternatives
considered

Aside from not making the additions that this proposal wishes to make to
the standard library no other alternatives have been considered.

_______________________________________________
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

There is already a `clamped` function for clamping one range to another and I feel that this function should be consistent with that one. As I see it, it can either be consistent in that it takes a Range as its argument, or in being an extension to Range. Probably something like either one of these:

extension Comparable { // or something else?
    func clamped(to range: Range<Self>) -> Self
}

extension Range {
    func clamping(_ value: Bound) -> Bound
}

Involving a range is good because that means that ensuring that the bounds checking (lower < upper) is already taken care of.

I do feel that this a useful addition to the standard library. But it is purely additive, so it should wait until after Phase 1.

- David

···

Sent from my iPad

On 2 Sep 2016, at 18:55, Nicholas Maccharoli via swift-evolution <swift-evolution@swift.org> wrote:

Introduction

The aim of this proposal is to introduce clamp functionality to the swift standard library. The clamp function would take a value and a upper and lower bounds to clamp the value to, ensuring that the return value of the function is within the range specified by the upper and lower bounds. Swift-evolution thread: Discussion thread topic for that proposal

Motivation

The standard library already includes functionality for min and max but at the time of this writing there is no global function for clamp. Adding a clamp function would complement min and max really well and would also eliminate the need for developers to write their own clamp functionality.

Proposed solution

I propose that a global clamp function akin to min and max be added to the standard library.

Detailed design

The implementation of the global clamp function would be as follows:

public func clamp<T : Comparable>(value: T, _ lower: T, _ upper: T) -> T {
  return max(lower, min(value, upper))
}
Impact on existing code

There are no impacts on existing code, this proposal is purely additive.

Alternatives considered

Aside from not making the additions that this proposal wishes to make to the standard library no other alternatives have been considered.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution