Hello everyone. I would like to propose to rename max and min:
withMax = min
withMin = max
Here is why:
If you need to give an upper and a lower bound for a value, then the clamp function can be used. But for only one bound it is not obvious at first, what function to use.
Me coming from a mathematical background, I know that min and max are the functions that I’m looking for, but once I read the code I get confused (min -> maximum, max -> minimum).
I noticed that Elm-Ui has the functions withMaximum and withMinimum. And that got me thinking, why don’t we rename the functions?
I think the biggest argument against this proposition is, that sometimes min and max are actually used to evaluate between two variables. I am wondering how often that actually happens.
Sounds like a perfect opportunity to have that in a utility module. Like you said, min and max are well established and I commonly use them the - supposedly - intended way but that might be because I come from JS
I think that would be super confusing and definitely think that ship has sailed a long time ago. While an upgrade could be automated it would make elm code pretty inconsistent with pretty much every other language out there.
I have the same problem! If this is the right solution, it feels like the upgrade path could go like % to modBy/divBy did in 0.19.1. That is:
remove max and min (so as to cause actual compilation errors instead of silent failures)
add withMax and withMin (or whatever names make sense)
That said, I think it makes a lot of sense to try this out in some large projects and see how it goes. Is it nicer to use? Does including max and min in the name make sense here or does it cause more confusion? (e.g. is it better to say withUpperBound/withLowerBound?) Getting answers to these would make a core library change more feasible here, even though the implementation is technically trivial.
Being familiar with max and min from other languages, your proposal just confuses me.
min gives me the minimum of the two arguments, while max gives me the maximum of the two arguments. Seems pretty straightforward, to me, anyway.
To assign intent to it (using for bounds) just muddles it, the function is simpler than that one use case. Its purpose is: the minimum of these two values.
Your proposal assumes that one of the arguments is some static bound that you’re really only comparing to one value you care about to. That metaphor breaks down when you have two dynamic values and you just want the higher or lower of the two.
Yeah, i believe you’re all right, min and max should stay as they are. Instead of the core module, it would make more sense to add the new functions to elm-community/basic-extra.
I’m with you on that.
I’ll add a PR to elm-community/basic-extra once i’m at home.
Maintainer of basics-extra here. I think it is confusing to include the words “max” and “min” in the names of the functions you are proposing. What do you think of calling the functions atMost and atLeast? As an example, List.sum percentages |> atMost 100.
Personally I don’t understand what the real problem here is? Max and min is as mentioned what it is called in most languages, and I would say it pretty accurately describes what the functions does. Adding it to a library would not harm or hurt at all, but at the same time I don’t understand what the fuzz is all about. Sure, rename it, but some one else with a slightly different use case is going to find it confusing… The suggestion of atMost seems just plane wrong, since it should give you the highest of two values, not |> atMost 100. The second parameter could be 200, which would give you 200 unless you implement a different function that caps the value at the first param (which is a perfectly good function, but not the max function).
Do we really need a change in the core library or a library at all for something that you could define yourself in two lines and call what ever makes sense to you?
To me it also makes no sense to rename min and max, but the motivation of this topic can be understood with the following examples:
maximumAllowedValue = 10
-- Imperative apporach: min behavior is clear, but readability is harder.
doSomething a b c =
min maximumAllowedValue (someCalculation a b c)
-- Current apporach: piping makes coding more lyrical,
-- but `min` signature kills readability.
doSomething a b c =
someCalculation
|> min maximumAllowedValue
-- Proposed approaches: refactor to have better readability
-- in this use case.
doSomething a b c =
someCalculation
|> withMax maximumAllowedValue
doSomething a b c =
someCalculation
|> atMost maximumAllowedValue
As you see, the code always does the same, but the way you read and think of it feels more natural. The problem with this proposal is that it only works in a specific context. Here, the proposed refactor doesn’t help:
-- Here, proposed refactor becomes the fuck up, because it is hard to see
-- that the two inputs are both value and roof, depending on the input.
youngerAge age1 age2 =
age1
|> atMost age2
-- Better readability like this.
youngerAge age1 age2 =
min age1 age2
-- Lyrical piping... let's see
youngerAge age1 age2 =
age1
|> min age2
youngerAge age1 age2 =
age1
|> smallestWith age2
I believe that since we are talking about numbers, and numbers are an abstract concept, they have no implicit meaning like, for example, if we would be talking about users. With users all functions would be scoped to work with users, so you would have functions like applyName, checkBirthday. Numbers can be energy, happiness, age, degrees, colors… anything. So I think that what makes more sense is to simply keep the traditional min and max names, which are agnostic to the context and they only state what they do: from all the inputs I give you, return the biggest/smallest.
Personally, I like having “Maximum” and “Minimum” in the name as it is the mathematically correct term. I feel like it would not matter a lot, so sure, we can call it atMost and atLeast if you want to.
Yes, I feel like adding these two functions is justified, because it legitimizes the use of min and max in such a way. It took me quite some time to understand that this is the correct use case.
Yeah, my plan would be to add two new functions to elm-community/basic-extra. Maybe at some point it would make sense to create a package around a Range data type and then add the functions to it, but for now that does not feel necessary.
I believe you misunderstood my counterproposal. atMost corresponds to min and atLeast corresponds to max.
I believe the point of this is to decide on a common language that the community can centralize behind. Besides, many of the functions that are already in basics-extra are relatively simple to implement yourself and some are even one-liners, so this in and of itself is not a reason to reject the proposal.
I don’t believe this is a problem. Coding style is inherently contextual. We can have min and max for the general case and the proposed functions for the pipelined case.
I don’t think the “mathematically correct term” should be the be-all and end-all when naming things in Elm. I believe the current state of the language backs me up on this point, for instance, in Elm we typically use andThen rather than >>= / bind.
(I also would like to push back on the idea that “max” and “min” are the mathematically correct term. In my mathematics experience, the language “at most” and “at least” is regularly used to refer to the concepts being discussed. Furthermore, in my experience, “max” and “min” in traditional mathematics typically operate on sets and occasionally functions but not pairs of values. I acknowledge that it could be that other branches of mathematics use this notation differently. At the end of the day though, I don’t think having this argument is productive.)