Why are not min! and max! macros in the std?


#1

Looking for maximum or minimum in a set of data is a repetitive job.
With the power of Rust macro expansion it is easy to do a macro that does the job for you.
So I made this recursive macro:

macro_rules! max {
    ($x: expr) => ($x);
    ($x: expr, $($z: expr),+) => {{
        let y = max!($($z),*);
        if $x > y {
            $x
        } else {
            y
        }
    }}
}

If you think it could be useful, why don’t add it to the standard library?

EDIT:
This is my version of min!, if anybody cares:

macro_rules! min {
    ($x: expr) => ($x);
    ($x: expr, $($z: expr),+) => {{
        let y = min!($($z),*);
        if $x < y {
            $x
        } else {
            y
        }
    }}
}

#2

Rust has built-in functions already to handle max/min. For two values, cmp::max makes sense. When you have an iterable list, iter::Iterator::max is used.

Including something in the standard library has a very high bar. Rust isn’t trying to have an all-inclusive standard library like Go, and so something like the max! and min! macros you described wouldn’t be a good fit. Their usefulness is limited to a situation where you have three or more values that you want to compare, but somehow don’t already exist in a Vec or an array. In those kinds of situations, you can just manually nest one or two calls to cmp::max (or cmp::min) and it isn’t a big deal.


#3

You could even use cmp::min/max in your macro, e.g.

macro_rules! min {
    ($x: expr) => ($x);
    ($x: expr, $($z: expr),+) => (::std::cmp::min($x, min!($($z),*)));
}

#4
  • cmp::min/max are annoying, because they don’t work with floats (NaNs, I know, I know)
  • and num.min()/num.max() don’t work with integers. (edit: it’s been fixed!)

#5

That’s true, and you need to be careful to only use affirmative comparisions to deal with NaN, i.e. only use a true < for min, not a false >, which @garro did correctly.


#6

There are no min/max macros because the min/max functions work at least as well, and likely will present better type checking as well as better errors when something goes wrong.

In addition, there is likely to be no performance gain from making them macros, and if there is, it’s always possible to have the min/max functions #[inline]d.

Generally speaking, it’s unwise to turn something into a macro when a function will do.