Live data from Hacker News

Math.min(Math.max(num, min), max)

twitter.com

31–40 of 291 posts

Re: Math.min(Math.max(num, min), max)

#32
post #18
post #15

[min, num, max].sort()[1]

sort() on JavaScript arrays sorts alphabetically (unless you pass a compareFunction) https://stackoverflow.com/questions/21019902/why-cant-javasc... https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

Wait, really? I just had to double-check my one JS project for bugs and either I used to know this gotcha or I got lucky. My sort()-ing needed to handle NaNs carefully so I was already using custom comparators.

Re: Math.min(Math.max(num, min), max)

#33
post #28

I find that the fact that the functions min and max have the same name as the variables min and max increases cognitive load which makes it harder to think about it. I find the following easier to read : Math.min(Math.max(num, lower_bound), upper_bound)

That doesn't really help. "Max" to enforce a "lower bound" is briefly halting.

Re: Math.min(Math.max(num, min), max)

#34
post #18
post #15

[min, num, max].sort()[1]

sort() on JavaScript arrays sorts alphabetically (unless you pass a compareFunction) https://stackoverflow.com/questions/21019902/why-cant-javasc... https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

Good point, for those who need to implement a slick compareFunction for numbers, Math.sign is great:

  [min, num, max].sort((a, b) => Math.sign(a - b))[1]
An entirely different alternative is poor man's match:

  switch (true) {
  case num > max: return max;
  case num 

Re: Math.min(Math.max(num, min), max)

#35
Do people actually have trouble with this repeatedly, or just when they first learn about it? I started using this implementation of clamp a few years ago, and while it gave me some trouble when I first implemented it, the pattern is very simple, and I got used to it very quickly.

I use Common Lisp:

> (max min (min max n))

Is the difference my choice of language, my personal mental hardware, the amount of familiarity one has with the pattern, or none of the above?

Re: Math.min(Math.max(num, min), max)

#36

Here's clamp in idiomatic Elixir (using multi-clause functions and guards): def clamp(min, _max, n) when n max, do: max def clamp(_min, _max, n), do: n

An Elixir convention I've seen is to put the thing you're operating on first, so that you can compose functions using the `|>` operator, which places the previous expression as the first argument of the function to the right.

Maybe something like this?

  defmodule Compare do
    def clamp(number, minimum, maximum) do
      number
      |> max(minimum)
      |> min(maximum)
    end
  end
  
  import Compare
  
  clamp(5, 1, 10) # 5
  clamp(1, 5, 10) # 5
  clamp(10, 1, 5) # 5
  
  
  some_number
  |> clamp(min, max)

As a side note, I think the Elixir |> operator is a stroke of genius that other languages should take a look at. Making the pipe operator append the _first_ argument has the following benefits

1.) It makes the most "important" argument of the function the first thing you read in function signatures

2.) If you need to add more arguments to a function signature later, they tend to be less important the original args, so they tend to make sense at the end

3.) It creates a convention for all libraries to follow so they can leverage the pipe operator. Its really jarring when the thing you want to put in a pipeline isn't the first argument (looking at you `Regex`[0] which puts the regular expression as the first arg and not the string)

[0] https://hexdocs.pm/elixir/Regex.html#replace/4

Post reply on HN