Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ER] Array.max and min ? #78504

Open
leonardo-m opened this issue Oct 28, 2020 · 6 comments
Open

[ER] Array.max and min ? #78504

leonardo-m opened this issue Oct 28, 2020 · 6 comments
Labels
A-const-generics Area: const generics (parameters and arguments) C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@leonardo-m
Copy link

When you want to compute the max or min of three or more items you have various options:

fn main() {
    let (a, b, c, d) = (10, 20, 30, 40);
    let m0 = a.max(b).max(c).max(d);
    let m2: u32 = [a, b, c, d].iter().copied().max().unwrap();
}

You can also introduce a macro:

#![feature(min_const_generics)]

macro_rules! max {
    ($x:expr) => ($x);
    ($x:expr, $($xs:expr),+) => {
        {
            std::cmp::max($x, max!( $($xs),+ ))
        }
    };
}

fn main() {
    let (a, b, c, d) = (10, 20, 30, 40);
    let m1 = max!{a, b, c, d};
}

But an array method may solve the problem better, without macros (code untested) and without unwraps:

// This should statically require N > 0.
impl<T: Ord, const N: usize> [T; N] {
    fn max(self) -> T {
        let mut result = self[0];
        for &x in &self[1 .. ] {
            result = result.max(x);
        }
        result
    }
}

fn main() {
    let (a, b, c, d) = (10, 20, 30, 40);
    let m3a: u32 = [a, b, c, d].min();
    let m3b: u32 = [a, b, c, d].max();
}
@camelid camelid added A-const-generics Area: const generics (parameters and arguments) C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Oct 28, 2020
@jyn514
Copy link
Member

jyn514 commented Oct 29, 2020

This will work: [1,2,3].iter().max().unwrap()

@jyn514
Copy link
Member

jyn514 commented Oct 29, 2020

Oh you said that already, sorry.

@jyn514
Copy link
Member

jyn514 commented Oct 29, 2020

This works on nightly: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=c2434427de054bbbb32950461920bb70. Not sure how to enforce the length is greater than 0.

@JulianKnodt
Copy link
Contributor

I think this would compile efficiently(and is the same as jyn's with an added assert which might change compilation behavior):

#![feature(iterator_fold_self)]
fn arr_max<T: Ord, const N: usize>(v: [T; N]) -> T {
  assert(N > 0); // This should get compiled out when N > 0 and when N == 0 this will just be a panic.
  // I would think the unwrap would be compiled out but unsure.
  Array::into_iter(v).fold_first(|a, b| a.max(b)).unwrap()
}

@leonardo-m
Copy link
Author

Now there are Nightly ways to enforce N > 0.
If the array::max() name is not available then array::array_max() and array::array_min() names could be acceptable.

A related function could be array::fold.

@sffc
Copy link

sffc commented Sep 25, 2024

I've landed here multiple times looking for a method on array that lets me do reduction operations without an unwrap. It would be nice to start with a .reduce function defined on array lengths of at least 1 that is not fallible; then one could write:

let arr: [i32; 4] = [10, 20, 30, 40];
let max = arr.reduce(i32::max);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-generics Area: const generics (parameters and arguments) C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants