Hacker News new | ask | show | jobs
by mauricio 2123 days ago
Always good to know the underlying implementation, but for any Ruby readers check out clamp(). It's been available since 2.4.

  25.clamp(5, 10)
  => 10

  6.clamp(5, 10)
  => 6

  1.clamp(5, 10)
  => 5
2 comments

I often see [a, b, c].sort[1] which I think is very neat.
I'd say the only way this would be better than min/max solution is that you can't accidentally flip it when writing the code - but IMO both suck at expressing intent, clamp reads unambiguously.
Yes but its too many operations for such a simple problem. No need to overwork the system when two conditionals can solve the problem.
If you are writing code that is clamping a lot of numbers, the GC churn from building a new array every time might be a problem.
Ideally the temporary array should optimise away.
Ideally, but so far my experiences with simple benchmarks and with ruby-prof have shown that CRuby doesn't make such optimizations:

https://repl.it/repls/GargantuanThistleLink

    Result from sort: 3 in 0.9785124980007822s
    Allocated 3000001 object(s)
    Result from ternary: 3 in 0.3205206830025418s
    Allocated 1 object(s)
    Result from clamp: 3 in 0.5030354310001712s
    Allocated 2 object(s)
Interestingly the ternary comparison is faster than clamp.
I find myself needing this most frequently in making graphics in R. The scales package has squish() with the same behavior:

squish(25, c(5, 10)) => 10

squish(6, c(5, 10)) => 6

squish(1, c(5, 10)) => 5

If you don't provide the limits it defaults to c(0, 1). That's because this function exists to map to a 0-to-1 range for functions that then map the [0, 1] range to a color ramp.