minOf and maxOf versus coerceAtLeast and coerceAtMost


#1

I was looking through the What’s New in Kotlin 1.1 page, and came across minOf() and maxOf(). The description there is pretty brief, but it sounds like these are essentially the same as coerceAtMost and coerceAtLeast, except they take an optional comparator, and they’re functions not methods.

I have to say I really prefer the minOf/maxOf names. Are there plans to deprecate coerceAtLeast and coerceAtMost?


#2

No there are no such plans, because these functions cover different use cases.

minOf/maxOf are top level functions for finding the minimum or maximum of two (or three) values.
val minSize = minOf(this.size, that.size)

On the other hand coerceAtLeast/AtMost are extension functions that are used when you have one value, and you want to ensure it’s within the given limits, for example:
val insertionPoint = index.coerceAtMost(lastIndex)

Therefore coerce* functions help to express the intent more clearly.


#3

I’m not really convinced that the coerceAtLeast/AtMost methods are much better expressing intent. Every time I’ve had to use the coerce methods I have a hard time figuring out which one I actually mean to use, even when I’m starting out with a value that I want to constrain to some limit(s). I never have that problem using “min” or “max” in other languages. Interestingly, I also don’t have that problem with coerceIn(min, max), and have even considered doing things like this for clarity:

x.coerceIn(0, x)

I also always have a really hard time remembering the names of these methods in the first place. I think part of what keeps throwing me off is that “coerce” normally means that it changes the type. I keep expecting these methods to be called “constrain” or maybe “clamp”.

The only advantage I see to the coerceAtLeast and coerceAtMost methods are that they make it obvious which object you’ll get when the two parameters are equal, whereas minOf and maxOf don’t (if they even guarantee one or the other).


#4

FTR I thought the same thing about the coerce* naming (that it sounds/feels like a type related thing) - we were also using clamp before they were added. Not sure if they can be changed at this point though unfortunately (though 1.1 not official yet so maybe they can be?)


#5

Suggestion for more parameters:

inline fun <T:Comparable<T>> max(vararg values:T) = values.max()

#6

Not knowing that there were such functions already in the Kotlin’s standard library, I implemented my own ‘clampMin’, ‘clampMax’ and ‘clamp’ extension functions, which is a common way to name something like this. Google ‘coerceAtLeast’ and ‘coerceAtMost’ however, and first page of results will refer to Kotlin. I personally prefer the ‘clamp*’ naming convention. ‘coerceAtLeast’ name is too creative (for reasons not clear to me) and long-winded, IMO.