Idiomatic Code?

Is this idiomatic rust?
I am trying my best at working with error messages.

//----------------------------------------------------------  
  match parse(s) {
        Ok(numbers) => {
            let count = count(&numbers);
            let median = median(&numbers);
            let mean = mean(&numbers);
            let min = minimum(&numbers);
            let max = maximum(&numbers);
            let mode = mode(&numbers);
            match (count, min,max, median, mean, mode) {
                (Some(count),
                    Some(min),
                        Some(max),
                             Some(mean), 
                                Some(median), 
                                    Some(mode)) => {
                                        println!("N {count}");
                                        println!("min {min}");
                                        println!("max {max}");
                                        println!("mean {mean}");
                                        println!("median {median}");
                                        println!("mode {mode:?}");
                                }
                _ => println!("Error: Empty List")

            }
        }
        Err(e) => print!("{e}"),
    }

There's at least a couple ways to reduce nesting:

  • ? operator
  • New let else syntax

would you be able to make an example?

This seems to work:

fn main() {
    let a = Some(1);
    let b = Some(2);
    let c = Some(3);
    //let c = None;
    let abc: Option<(i32, i32, i32)> = (|| Some((a?, b?, c?)))();
    println!("{:?}", abc);
}

(Playground)

Output:

Some((1, 2, 3))


Even without the type annotation:

-    let abc: Option<(i32, i32, i32)> = (|| Some((a?, b?, c?)))();
+    let abc = (|| Some((a?, b?, c?)))();

(Playground)

1 Like

Note that the original example in the OP isn't actually deeply nested, even though the formatting suggests.

1 Like

something like this? because the parse function is a result and stops everything when the user tries to submit a empty list

      match parse(s) {
        Ok(numbers) => { 
            let count = Some(count(&numbers));
            println!("{:?}", count);

        }
        Err(e) => println!("{e}")

I meant you can use the (|| Some((a?, b?, c?)))() syntax to convert an (Option<A>, Option<B>, Option<B>) into an Option<(a, b, c)>. Then you can do a single match for that option against Some(a, b, c), instead of (Some(a), Some(b), Some(c)).

Not sure which is more idiomatic though.


Ahh, your point isn't the (seemingly) nested match, but the double error reporting here?

I am wondering if there is a better way of writing this avoiding the big list of Some(),
and the yes the error messages are pretty much redundant, a list of length of 0 will output None for all the stat functions

Maybe a little strange, but you can use a function that returns Option and use ? within it.

#[test]
fn xxx() {
    fn yyy() -> Option<()> {
        let a = Some(1)?;
        let b = Some(2)?;
        let c = Some(3)?;
        // let c: i32 = None?;
        println!("{a} {b} {c}");
        Some(())
    }
    assert_eq!(Some(()), yyy());
}

The better way is probably to put this in a method where ? applies.

I suggest making a struct for your statistics.

2 Likes