[Python-ideas] Consider adding clip or clamp function to math
Steven D'Aprano
steve at pearwood.info
Fri Aug 5 02:06:48 EDT 2016
On Fri, Aug 05, 2016 at 12:09:09PM +0900, Stephen J. Turnbull wrote:
> Steven D'Aprano writes:
>
> > > clamp(x, y, z) --> NaN if z < y
> >
> > That's a clear error, and it should raise immediately. I see no
> > advantage to returning NAN in this case.
> >
> > Think about why you're clamping. It's unlikely to be used just once, for
> > a single calculation. You're likely to be clamping a whole series of
> > values, with a fixed lower and upper bounds.
>
> "Likely" isn't a good enough reason:
Of course it is. We write code to prefer known, common use-cases, not
just hypothetical "What If" scenarios.
E.g. most trig functions (sin, cos, tan) take angles in radians. I've
seen a few take angles in degrees. I've even seen trig functions that
take their argument as a multiple of pi (e.g. sinpi(1.25) being
equivalent to sin(1.25*pi), only more accurate). All of these have good
use-cases.
But I'm willing to bet that you will never, ever find a general purpose
programming language or maths library with specialised trig functions
that take arguments in 1/37th of a gon. (Yes, "gon" is a real unit.) If
you need such a thing, you write it yourself.
Chris has already gone through his code and confirmed what I expected:
he uses "clamp" extensively, and the bounds are invariably fixed once at
the start of the loop.
But if you find yourself in that unusual situation of needing something
unusual, you can easily write your own wrapper:
def clamp(value, lower, upper):
if lower > upper:
return "Surprise!"
return math.clamp(value, lower, upper)
Of course, if math.clamp() returned NAN, you could just as easily go the
other way and write a wrapper to raise instead. Neither case is
particularly onerous.
But in one case, only a few people will need to wrap the function; in
the second case, many people (possibly even *everybody*) will want to
wrap the function to avoid the unhelpful standard behaviour. It is our
job as function designers to try to cater for the majority, not the
minority, when possible.
> x = [clamp(x[t], f(t), g(t)) for t in range(1_000_000)]
>
> is perfectly plausible code.
I have my doubts. Sure, you can write it, but what would you use it for?
What's your use-case?
--
Steve
More information about the Python-ideas
mailing list