erlang / otp

Erlang/OTP
http://erlang.org
Apache License 2.0
11.31k stars 2.94k forks source link

Allow usage of `min/2` and `max/2` in guards #6544

Closed hauleth closed 1 year ago

hauleth commented 1 year ago

Is your feature request related to a problem? Please describe.

It come up when I was working on AoC 2022 Day 9. It would make it a little bit cleaner if I could use these in guards in similar way that we can use abs/1.

Describe the solution you'd like

It would simply return smaller/bigger value of the arguments. It is quite cheap to do (it is not more expensive than '<'/2 which is allowed in guards) and it could be handy in few situations.

Describe alternatives you've considered

Currently we can do it by changing our guard to 2 anded/ored statements, so for example:

foo({X1, Y1}, {X2, Y2}) where max(abs(X1 - X2), abs(Y1 - Y2)) < 2 ->

Can be written as:

foo({X1, Y1}, {X2, Y2}) where abs(X1 - X2) < 2 and abs(Y1 - Y2) < 2 ->

But max/2 make it IMHO a little bit clearer about context.

Additional context

min/2 and max/2 are both constant-time-ish (aka, not more expensive than '<'/2). Unfortunately currently these aren't BIFs, but it shouldn't be really hard to make them such.

hauleth commented 1 year ago

This would also allow to have more sophisticated constructs available in guards, like clamp(Min, Value, Max) (aka min(Max, max(Value, Min)).

tsloughter commented 1 year ago

If a bif would mean it could be used in a matchspec body that'd be awesome too for shrinking matchspecs like https://github.com/open-telemetry/opentelemetry-erlang/blob/main/apps/opentelemetry_experimental/src/otel_aggregation_histogram_explicit.erl#L66-L115 :)

bjorng commented 1 year ago

The OTP team likes this idea. We'll try to implement in OTP 26.

@tsloughter Making them guard BIFs should make it trivial to also support them in match specs.